#include "cupsd.h"
#ifdef __APPLE__
# include <CoreFoundation/CFString.h>
# include <CoreFoundation/CFStringEncodingExt.h>
static void apple_conv_utf8(char **str, const char *encoding);
#endif
#ifdef HAVE_NOTIFY_H
# include <notify.h>
#endif
static void SetMimeTypesAttr(printer_t *p);
#ifdef __sgi
static void write_irix_config(printer_t *p);
static void write_irix_state(printer_t *p);
#endif
printer_t *
AddPrinter(const char *name)
{
printer_t *p,
*current,
*prev;
LogMessage(L_DEBUG2, "AddPrinter(\"%s\")", name ? name : "(null)");
if (name == NULL)
return (NULL);
if ((p = calloc(1, sizeof(printer_t))) == NULL)
{
LogMessage(L_ERROR, "Unable to allocate memory for printer - %s",
strerror(errno));
return (NULL);
}
SetString(&p->name, name);
SetString(&p->info, name);
SetString(&p->hostname, ServerName);
SetStringf(&p->uri, "ipp://%s:%d/printers/%s", ServerName,
ntohs(Listeners[0].address.sin_port), name);
SetStringf(&p->device_uri, "file:/dev/null");
p->state = IPP_PRINTER_STOPPED;
p->accepting = 0;
p->filetype = mimeAddType(MimeDatabase, "printer", name);
SetString(&p->job_sheets[0], "none");
SetString(&p->job_sheets[1], "none");
if (MaxPrinterHistory)
p->history = calloc(MaxPrinterHistory, sizeof(ipp_t *));
for (prev = NULL, current = Printers;
current != NULL;
prev = current, current = current->next)
if (strcasecmp(p->name, current->name) < 0)
break;
if (prev == NULL)
Printers = p;
else
prev->next = p;
p->next = current;
WritePrintcap();
#ifdef HAVE_NOTIFY_POST
if (!NotifyPaused)
{
LogMessage(L_DEBUG2, "AddPrinter: notify com.apple.printerListChange");
NotifyPending = 0;
notify_post("com.apple.printerListChange");
}
else
NotifyPending = 1;
#endif
return (p);
}
void
AddPrinterFilter(printer_t *p,
const char *filter)
{
int i;
char super[MIME_MAX_SUPER],
type[MIME_MAX_TYPE],
program[1024];
int cost;
mime_type_t **temptype;
if (p == NULL || p->filetype == NULL || filter == NULL)
return;
if (sscanf(filter, "%15[^/]/%31s%d%1023s", super, type, &cost, program) != 4)
{
LogMessage(L_ERROR, "AddPrinterFilter: Invalid filter string \"%s\"!",
filter);
return;
}
for (temptype = MimeDatabase->types, i = MimeDatabase->num_types;
i > 0;
i --, temptype ++)
if (((super[0] == '*' && strcasecmp((*temptype)->super, "printer") != 0) ||
strcasecmp((*temptype)->super, super) == 0) &&
(type[0] == '*' || strcasecmp((*temptype)->type, type) == 0))
{
LogMessage(L_DEBUG2, "Adding filter %s/%s %s/%s %d %s",
(*temptype)->super, (*temptype)->type,
p->filetype->super, p->filetype->type,
cost, program);
mimeAddFilter(MimeDatabase, *temptype, p->filetype, cost, program);
}
}
void
AddPrinterHistory(printer_t *p)
{
ipp_t *history;
if (MaxPrinterHistory <= 0)
return;
p->sequence_number ++;
if (p->num_history >= MaxPrinterHistory)
{
p->num_history --;
ippDelete(p->history[0]);
memmove(p->history, p->history + 1, p->num_history * sizeof(ipp_t *));
}
history = ippNew();
ippAddInteger(history, IPP_TAG_PRINTER, IPP_TAG_ENUM, "printer-state",
p->state);
ippAddBoolean(history, IPP_TAG_PRINTER, "printer-is-accepting-jobs",
p->accepting);
ippAddString(history, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-state-message",
NULL, p->state_message);
if (p->num_reasons == 0)
ippAddString(history, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
"printer-state-reasons", NULL,
p->state == IPP_PRINTER_STOPPED ? "paused" : "none");
else
ippAddStrings(history, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
"printer-state-reasons", p->num_reasons, NULL,
(const char * const *)p->reasons);
ippAddInteger(history, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
"printer-state-time", p->state_time);
ippAddInteger(history, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
"printer-state-sequence-number", p->sequence_number);
p->history[p->num_history] = history;
p->num_history ++;
#ifdef HAVE_NOTIFY_POST
notify_post("com.apple.printerHistoryChange");
#endif
}
void
AddPrinterUser(printer_t *p,
const char *username)
{
const char **temp;
if (!p || !username)
return;
if (p->num_users == 0)
temp = malloc(sizeof(char **));
else
temp = realloc(p->users, sizeof(char **) * (p->num_users + 1));
if (!temp)
return;
p->users = temp;
temp += p->num_users;
if ((*temp = strdup(username)) != NULL)
p->num_users ++;
}
void
DeleteAllPrinters(void)
{
printer_t *p,
*next;
for (p = Printers; p != NULL; p = next)
{
next = p->next;
if (!(p->type & CUPS_PRINTER_CLASS))
DeletePrinter(p, 0);
}
if (CommonData)
{
ippDelete(CommonData);
CommonData = NULL;
}
}
void
DeletePrinter(printer_t *p,
int update)
{
int i;
printer_t *current,
*prev;
#ifdef __sgi
char filename[1024];
#endif
DEBUG_printf(("DeletePrinter(%08x): p->name = \"%s\"...\n", p, p->name));
if (p == NULL)
return;
for (prev = NULL, current = Printers;
current != NULL;
prev = current, current = current->next)
if (p == current)
break;
if (current == NULL)
{
LogMessage(L_ERROR, "Tried to delete a non-existent printer %s!\n",
p->name);
return;
}
if (prev == NULL)
Printers = p->next;
else
prev->next = p->next;
StopPrinter(p, update);
#ifdef __sgi
snprintf(filename, sizeof(filename), "/var/spool/lp/interface/%s", p->name);
unlink(filename);
snprintf(filename, sizeof(filename), "/var/spool/lp/gui_interface/ELF/%s.gui",
p->name);
unlink(filename);
snprintf(filename, sizeof(filename), "/var/spool/lp/activeicons/%s", p->name);
unlink(filename);
snprintf(filename, sizeof(filename), "/var/spool/lp/pod/%s.config", p->name);
unlink(filename);
snprintf(filename, sizeof(filename), "/var/spool/lp/pod/%s.status", p->name);
unlink(filename);
snprintf(filename, sizeof(filename), "/var/spool/lp/member/%s", p->name);
unlink(filename);
#endif
if (p == DefaultPrinter)
{
DefaultPrinter = Printers;
WritePrintcap();
}
if (!(p->type & (CUPS_PRINTER_CLASS | CUPS_PRINTER_IMPLICIT)))
DeletePrinterFromClasses(p);
if (p->printers != NULL)
free(p->printers);
if (MaxPrinterHistory)
{
for (i = 0; i < p->num_history; i ++)
ippDelete(p->history[i]);
free(p->history);
}
for (i = 0; i < p->num_reasons; i ++)
free(p->reasons[i]);
ippDelete(p->attrs);
DeletePrinterFilters(p);
FreePrinterUsers(p);
FreeQuotas(p);
ClearString(&p->uri);
ClearString(&p->hostname);
ClearString(&p->name);
ClearString(&p->location);
ClearString(&p->make_model);
ClearString(&p->info);
ClearString(&p->job_sheets[0]);
ClearString(&p->job_sheets[1]);
ClearString(&p->device_uri);
free(p);
WritePrintcap();
#ifdef HAVE_NOTIFY_POST
if (!NotifyPaused)
{
LogMessage(L_DEBUG2, "DeletePrinter: notify com.apple.printerListChange");
NotifyPending = 0;
notify_post("com.apple.printerListChange");
}
else
NotifyPending = 1;
#endif
}
void
DeletePrinterFilters(printer_t *p)
{
int i;
mime_filter_t *filter;
if (p == NULL)
return;
for (filter = MimeDatabase->filters, i = MimeDatabase->num_filters;
i > 0;
i --, filter ++)
if (filter->dst == p->filetype)
{
MimeDatabase->num_filters --;
if (i > 1)
memmove(filter, filter + 1, sizeof(mime_filter_t) * (i - 1));
filter --;
}
}
printer_t *
FindDest(const char *name)
{
printer_t *p;
int diff;
for (p = Printers; p != NULL; p = p->next)
if ((diff = strcasecmp(name, p->name)) == 0)
return (p);
else if (diff < 0)
return (NULL);
return (NULL);
}
printer_t *
FindPrinter(const char *name)
{
printer_t *p;
int diff;
for (p = Printers; p != NULL; p = p->next)
if ((diff = strcasecmp(name, p->name)) == 0 &&
!(p->type & CUPS_PRINTER_CLASS))
return (p);
else if (diff < 0)
return (NULL);
return (NULL);
}
void
FreePrinterUsers(printer_t *p)
{
int i;
if (!p || !p->num_users)
return;
for (i = 0; i < p->num_users; i ++)
free((void *)p->users[i]);
free(p->users);
p->num_users = 0;
p->users = NULL;
}
void
LoadAllPrinters(void)
{
cups_file_t *fp;
int linenum;
int len;
char line[1024],
name[256],
*nameptr,
*value,
*valueptr;
printer_t *p;
snprintf(line, sizeof(line), "%s/printers.conf", ServerRoot);
if ((fp = cupsFileOpen(line, "r")) == NULL)
{
LogMessage(L_ERROR, "LoadAllPrinters: Unable to open %s - %s", line,
strerror(errno));
return;
}
linenum = 0;
p = NULL;
while (cupsFileGets(fp, line, sizeof(line)) != NULL)
{
linenum ++;
if (line[0] == '#')
continue;
len = strlen(line);
while (len > 0 && isspace(line[len - 1]))
{
len --;
line[len] = '\0';
}
for (value = line; isspace(*value); value ++);
for (nameptr = name; *value != '\0' && !isspace(*value) &&
nameptr < (name + sizeof(name) - 1);)
*nameptr++ = *value++;
*nameptr = '\0';
while (isspace(*value))
value ++;
if (name[0] == '\0')
continue;
if (strcmp(name, "<Printer") == 0 ||
strcmp(name, "<DefaultPrinter") == 0)
{
if (line[len - 1] == '>' && p == NULL)
{
line[len - 1] = '\0';
LogMessage(L_DEBUG, "LoadAllPrinters: Loading printer %s...", value);
p = AddPrinter(value);
p->accepting = 1;
p->state = IPP_PRINTER_IDLE;
if (strcmp(name, "<DefaultPrinter") == 0)
DefaultPrinter = p;
}
else
{
LogMessage(L_ERROR, "Syntax error on line %d of printers.conf.",
linenum);
return;
}
}
else if (strcmp(name, "</Printer>") == 0)
{
if (p != NULL)
{
SetPrinterAttrs(p);
AddPrinterHistory(p);
p = NULL;
}
else
{
LogMessage(L_ERROR, "Syntax error on line %d of printers.conf.",
linenum);
return;
}
}
else if (p == NULL)
{
LogMessage(L_ERROR, "Syntax error on line %d of printers.conf.",
linenum);
return;
}
else if (strcmp(name, "Info") == 0)
SetString(&p->info, value);
else if (strcmp(name, "Location") == 0)
SetString(&p->location, value);
else if (strcmp(name, "DeviceURI") == 0)
SetString(&p->device_uri, value);
else if (strcmp(name, "State") == 0)
{
if (strcasecmp(value, "idle") == 0)
p->state = IPP_PRINTER_IDLE;
else if (strcasecmp(value, "stopped") == 0)
p->state = IPP_PRINTER_STOPPED;
}
else if (strcmp(name, "StateMessage") == 0)
{
while (isspace(*value))
value ++;
strlcpy(p->state_message, value, sizeof(p->state_message));
}
else if (strcmp(name, "Accepting") == 0)
{
if (strcasecmp(value, "yes") == 0)
p->accepting = 1;
else
p->accepting = 0;
}
else if (strcmp(name, "JobSheets") == 0)
{
for (valueptr = value; *valueptr && !isspace(*valueptr); valueptr ++);
if (*valueptr)
*valueptr++ = '\0';
SetString(&p->job_sheets[0], value);
while (isspace(*valueptr))
valueptr ++;
if (*valueptr)
{
for (value = valueptr; *valueptr && !isspace(*valueptr); valueptr ++);
if (*valueptr)
*valueptr++ = '\0';
SetString(&p->job_sheets[1], value);
}
}
else if (strcmp(name, "AllowUser") == 0)
{
p->deny_users = 0;
AddPrinterUser(p, value);
}
else if (strcmp(name, "DenyUser") == 0)
{
p->deny_users = 1;
AddPrinterUser(p, value);
}
else if (strcmp(name, "QuotaPeriod") == 0)
p->quota_period = atoi(value);
else if (strcmp(name, "PageLimit") == 0)
p->page_limit = atoi(value);
else if (strcmp(name, "KLimit") == 0)
p->k_limit = atoi(value);
else
{
LogMessage(L_ERROR, "Unknown configuration directive %s on line %d of printers.conf.",
name, linenum);
}
}
cupsFileClose(fp);
}
void
SaveAllPrinters(void)
{
int i;
cups_file_t *fp;
char temp[1024];
char backup[1024];
printer_t *printer;
time_t curtime;
struct tm *curdate;
snprintf(temp, sizeof(temp), "%s/printers.conf", ServerRoot);
snprintf(backup, sizeof(backup), "%s/printers.conf.O", ServerRoot);
if (rename(temp, backup))
LogMessage(L_ERROR, "Unable to backup printers.conf - %s", strerror(errno));
if ((fp = cupsFileOpen(temp, "w")) == NULL)
{
LogMessage(L_ERROR, "Unable to save printers.conf - %s", strerror(errno));
if (rename(backup, temp))
LogMessage(L_ERROR, "Unable to restore printers.conf - %s", strerror(errno));
return;
}
else
LogMessage(L_INFO, "Saving printers.conf...");
fchown(cupsFileNumber(fp), getuid(), Group);
#ifdef __APPLE__
fchmod(cupsFileNumber(fp), 0600);
#else
fchmod(cupsFileNumber(fp), ConfigFilePerm);
#endif
curtime = time(NULL);
curdate = localtime(&curtime);
strftime(temp, sizeof(temp) - 1, CUPS_STRFTIME_FORMAT, curdate);
cupsFilePuts(fp, "# Printer configuration file for " CUPS_SVERSION "\n");
cupsFilePrintf(fp, "# Written by cupsd on %s\n", temp);
for (printer = Printers; printer != NULL; printer = printer->next)
{
if ((printer->type & CUPS_PRINTER_REMOTE) ||
(printer->type & CUPS_PRINTER_CLASS) ||
(printer->type & CUPS_PRINTER_IMPLICIT))
continue;
if (printer == DefaultPrinter)
cupsFilePrintf(fp, "<DefaultPrinter %s>\n", printer->name);
else
cupsFilePrintf(fp, "<Printer %s>\n", printer->name);
if (printer->info)
cupsFilePrintf(fp, "Info %s\n", printer->info);
if (printer->location)
cupsFilePrintf(fp, "Location %s\n", printer->location);
if (printer->device_uri)
cupsFilePrintf(fp, "DeviceURI %s\n", printer->device_uri);
if (printer->state == IPP_PRINTER_STOPPED)
{
cupsFilePuts(fp, "State Stopped\n");
cupsFilePrintf(fp, "StateMessage %s\n", printer->state_message);
}
else
cupsFilePuts(fp, "State Idle\n");
if (printer->accepting)
cupsFilePuts(fp, "Accepting Yes\n");
else
cupsFilePuts(fp, "Accepting No\n");
cupsFilePrintf(fp, "JobSheets %s %s\n", printer->job_sheets[0],
printer->job_sheets[1]);
cupsFilePrintf(fp, "QuotaPeriod %d\n", printer->quota_period);
cupsFilePrintf(fp, "PageLimit %d\n", printer->page_limit);
cupsFilePrintf(fp, "KLimit %d\n", printer->k_limit);
for (i = 0; i < printer->num_users; i ++)
cupsFilePrintf(fp, "%sUser %s\n", printer->deny_users ? "Deny" : "Allow",
printer->users[i]);
cupsFilePuts(fp, "</Printer>\n");
#ifdef __sgi
write_irix_state(printer);
#endif
}
cupsFileClose(fp);
}
void
SetPrinterAttrs(printer_t *p)
{
char uri[HTTP_MAX_URI];
char method[HTTP_MAX_URI],
username[HTTP_MAX_URI],
host[HTTP_MAX_URI],
resource[HTTP_MAX_URI];
int port;
int i;
char filename[1024];
int num_media;
location_t *auth;
const char *auth_supported;
cups_ptype_t printer_type;
ppd_file_t *ppd;
ppd_option_t *input_slot,
*media_type,
*page_size,
*output_bin,
*media_quality;
ppd_attr_t *ppdattr;
ipp_attribute_t *attr;
ipp_value_t *val;
static const int nups[] =
{ 1, 2, 4, 6, 9, 16 };
static const ipp_orient_t orients[4] =
{
IPP_PORTRAIT,
IPP_LANDSCAPE,
IPP_REVERSE_LANDSCAPE,
IPP_REVERSE_PORTRAIT
};
static const char * const sides[3] =
{
"one",
"two-long-edge",
"two-short-edge"
};
static const char * const versions[] =
{
"1.0",
"1.1"
};
static const ipp_op_t ops[] =
{
IPP_PRINT_JOB,
IPP_VALIDATE_JOB,
IPP_CREATE_JOB,
IPP_SEND_DOCUMENT,
IPP_CANCEL_JOB,
IPP_GET_JOB_ATTRIBUTES,
IPP_GET_JOBS,
IPP_GET_PRINTER_ATTRIBUTES,
IPP_HOLD_JOB,
IPP_RELEASE_JOB,
IPP_PAUSE_PRINTER,
IPP_RESUME_PRINTER,
IPP_PURGE_JOBS,
IPP_SET_JOB_ATTRIBUTES,
IPP_ENABLE_PRINTER,
IPP_DISABLE_PRINTER,
CUPS_GET_DEFAULT,
CUPS_GET_PRINTERS,
CUPS_ADD_PRINTER,
CUPS_DELETE_PRINTER,
CUPS_GET_CLASSES,
CUPS_ADD_CLASS,
CUPS_DELETE_CLASS,
CUPS_ACCEPT_JOBS,
CUPS_REJECT_JOBS,
CUPS_GET_DEVICES,
CUPS_GET_PPDS,
IPP_RESTART_JOB
};
static const char * const charsets[] =
{
"us-ascii",
"iso-8859-1",
"iso-8859-2",
"iso-8859-3",
"iso-8859-4",
"iso-8859-5",
"iso-8859-6",
"iso-8859-7",
"iso-8859-8",
"iso-8859-9",
"iso-8859-10",
"iso-8859-13",
"iso-8859-14",
"iso-8859-15",
"utf-8",
"windows-874",
"windows-1250",
"windows-1251",
"windows-1252",
"windows-1253",
"windows-1254",
"windows-1255",
"windows-1256",
"windows-1257",
"windows-1258",
"koi8-r",
"koi8-u",
};
static const char * const compressions[] =
{
#ifdef HAVE_LIBZ
"none",
"gzip"
#else
"none"
#endif
};
int num_finishings;
ipp_finish_t finishings[5];
static const char * const multiple_document_handling[] =
{
"separate-documents-uncollated-copies",
"separate-documents-collated-copies"
};
DEBUG_printf(("SetPrinterAttrs: entering name = %s, type = %x\n", p->name,
p->type));
if (!CommonData)
{
CommonData = ippNew();
ippAddString(CommonData, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
"pdl-override-supported", NULL, "not-attempted");
ippAddStrings(CommonData, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
"ipp-versions-supported", sizeof(versions) / sizeof(versions[0]),
NULL, versions);
ippAddIntegers(CommonData, IPP_TAG_PRINTER, IPP_TAG_ENUM, "operations-supported",
sizeof(ops) / sizeof(ops[0]) + JobFiles - 1, (int *)ops);
ippAddBoolean(CommonData, IPP_TAG_PRINTER, "multiple-document-jobs-supported", 1);
ippAddInteger(CommonData, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
"multiple-operation-time-out", 60);
ippAddStrings(CommonData, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
"multiple-document-handling-supported",
sizeof(multiple_document_handling) /
sizeof(multiple_document_handling[0]), NULL,
multiple_document_handling);
ippAddString(CommonData, IPP_TAG_PRINTER, IPP_TAG_CHARSET, "charset-configured",
NULL, DefaultCharset);
ippAddStrings(CommonData, IPP_TAG_PRINTER, IPP_TAG_CHARSET, "charset-supported",
sizeof(charsets) / sizeof(charsets[0]), NULL, charsets);
ippAddString(CommonData, IPP_TAG_PRINTER, IPP_TAG_LANGUAGE,
"natural-language-configured", NULL, DefaultLanguage);
ippAddString(CommonData, IPP_TAG_PRINTER, IPP_TAG_LANGUAGE,
"generated-natural-language-supported", NULL, DefaultLanguage);
ippAddString(CommonData, IPP_TAG_PRINTER, IPP_TAG_MIMETYPE,
"document-format-default", NULL, "application/octet-stream");
#ifndef __APPLE__
ippAddStrings(CommonData, IPP_TAG_PRINTER,
(ipp_tag_t)(IPP_TAG_MIMETYPE | IPP_TAG_COPY),
"document-format-supported", NumMimeTypes, NULL, MimeTypes);
#endif
ippAddStrings(CommonData, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
"compression-supported",
sizeof(compressions) / sizeof(compressions[0]),
NULL, compressions);
ippAddInteger(CommonData, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
"job-priority-supported", 100);
ippAddInteger(CommonData, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
"job-priority-default", 50);
ippAddRange(CommonData, IPP_TAG_PRINTER, "copies-supported", MinCopies, MaxCopies);
ippAddInteger(CommonData, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
"copies-default", 1);
ippAddBoolean(CommonData, IPP_TAG_PRINTER, "page-ranges-supported", 1);
ippAddIntegers(CommonData, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
"number-up-supported", sizeof(nups) / sizeof(nups[0]), nups);
ippAddInteger(CommonData, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
"number-up-default", 1);
ippAddIntegers(CommonData, IPP_TAG_PRINTER, IPP_TAG_ENUM,
"orientation-requested-supported", 4, (int *)orients);
ippAddInteger(CommonData, IPP_TAG_PRINTER, IPP_TAG_ENUM,
"orientation-requested-default", IPP_PORTRAIT);
if (NumBanners > 0)
{
if (Classification && !ClassifyOverride)
attr = ippAddString(CommonData, IPP_TAG_PRINTER, IPP_TAG_NAME,
"job-sheets-supported", NULL, Classification);
else
attr = ippAddStrings(CommonData, IPP_TAG_PRINTER, IPP_TAG_NAME,
"job-sheets-supported", NumBanners + 1, NULL, NULL);
if (attr == NULL)
LogMessage(L_EMERG, "SetPrinterAttrs: Unable to allocate memory for "
"job-sheets-supported attribute: %s!",
strerror(errno));
else if (!Classification || ClassifyOverride)
{
attr->values[0].string.text = strdup("none");
for (i = 0; i < NumBanners; i ++)
attr->values[i + 1].string.text = strdup(Banners[i].name);
}
}
}
DeletePrinterFilters(p);
AddPrinterFilter(p, "application/vnd.cups-raw 0 -");
auth_supported = "requesting-user-name";
if (!(p->type & CUPS_PRINTER_REMOTE))
{
if (p->type & CUPS_PRINTER_CLASS)
snprintf(resource, sizeof(resource), "/classes/%s", p->name);
else
snprintf(resource, sizeof(resource), "/printers/%s", p->name);
if ((auth = FindBest(resource, HTTP_POST)) != NULL)
{
if (auth->type == AUTH_BASIC || auth->type == AUTH_BASICDIGEST)
auth_supported = "basic";
else if (auth->type == AUTH_DIGEST)
auth_supported = "digest";
}
}
if (p->attrs)
ippDelete(p->attrs);
p->attrs = ippNew();
ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_URI, "printer-uri-supported",
NULL, p->uri);
ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
"uri-authentication-supported", NULL, auth_supported);
ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
"uri-security-supported", NULL, "none");
ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_NAME, "printer-name", NULL,
p->name);
ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-location",
NULL, p->location ? p->location : "");
ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-info",
NULL, p->info ? p->info : "");
ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_URI, "printer-more-info",
NULL, p->uri);
if (p->num_users)
{
if (p->deny_users)
ippAddStrings(p->attrs, IPP_TAG_PRINTER, IPP_TAG_NAME,
"requesting-user-name-denied", p->num_users, NULL,
p->users);
else
ippAddStrings(p->attrs, IPP_TAG_PRINTER, IPP_TAG_NAME,
"requesting-user-name-allowed", p->num_users, NULL,
p->users);
}
ippAddInteger(p->attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
"job-quota-period", p->quota_period);
ippAddInteger(p->attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
"job-k-limit", p->k_limit);
ippAddInteger(p->attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
"job-page-limit", p->page_limit);
if (NumBanners > 0 && !(p->type & CUPS_PRINTER_REMOTE))
{
attr = ippAddStrings(p->attrs, IPP_TAG_PRINTER, IPP_TAG_NAME,
"job-sheets-default", 2, NULL, NULL);
if (attr != NULL)
{
attr->values[0].string.text = strdup(Classification ?
Classification : p->job_sheets[0]);
attr->values[1].string.text = strdup(Classification ?
Classification : p->job_sheets[1]);
}
}
printer_type = p->type;
p->raw = 0;
if (p->type & CUPS_PRINTER_REMOTE)
{
ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_TEXT,
"printer-make-and-model", NULL, p->make_model);
p->raw = 1;
}
else
{
p->type &= ~CUPS_PRINTER_OPTIONS;
if (p->type & (CUPS_PRINTER_CLASS | CUPS_PRINTER_IMPLICIT))
{
if ((p->type & CUPS_PRINTER_IMPLICIT) && p->num_printers > 0)
ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_TEXT,
"printer-make-and-model", NULL, p->printers[0]->make_model);
else
ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_TEXT,
"printer-make-and-model", NULL, "Local Printer Class");
if (p->num_printers > 0)
{
attr = ippAddStrings(p->attrs, IPP_TAG_PRINTER, IPP_TAG_URI,
"member-uris", p->num_printers, NULL, NULL);
p->type |= CUPS_PRINTER_OPTIONS;
for (i = 0; i < p->num_printers; i ++)
{
if (attr != NULL)
attr->values[i].string.text = strdup(p->printers[i]->uri);
p->type &= ~CUPS_PRINTER_OPTIONS | p->printers[i]->type;
}
attr = ippAddStrings(p->attrs, IPP_TAG_PRINTER, IPP_TAG_NAME,
"member-names", p->num_printers, NULL, NULL);
if (attr != NULL)
{
for (i = 0; i < p->num_printers; i ++)
attr->values[i].string.text = strdup(p->printers[i]->name);
}
}
}
else
{
if (!p->device_uri)
strcpy(uri, "file:/dev/null");
else if (strstr(p->device_uri, "://") != NULL)
{
SanitizeURI(uri, sizeof(uri), p->device_uri);
}
else
{
strlcpy(uri, p->device_uri, sizeof(uri));
}
ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_URI, "device-uri", NULL,
uri);
p->type |= CUPS_PRINTER_BW;
finishings[0] = IPP_FINISHINGS_NONE;
num_finishings = 1;
snprintf(filename, sizeof(filename), "%s/ppd/%s.ppd", ServerRoot,
p->name);
if ((ppd = ppdOpenFile(filename)) != NULL)
{
if (ppd->color_device)
p->type |= CUPS_PRINTER_COLOR;
if (ppd->variable_sizes)
p->type |= CUPS_PRINTER_VARIABLE;
if (!ppd->manual_copies)
p->type |= CUPS_PRINTER_COPIES;
if ((ppdattr = ppdFindAttr(ppd, "cupsFax", NULL)) != NULL)
if (ppdattr->value && !strcasecmp(ppdattr->value, "true"))
p->type |= CUPS_PRINTER_FAX;
ippAddBoolean(p->attrs, IPP_TAG_PRINTER, "color-supported",
ppd->color_device);
if (ppd->throughput)
ippAddInteger(p->attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
"pages-per-minute", ppd->throughput);
if (ppd->nickname)
SetString(&p->make_model, ppd->nickname);
else if (ppd->modelname)
SetString(&p->make_model, ppd->modelname);
else
SetString(&p->make_model, "Bad PPD File");
#ifdef __APPLE__
if (ppd->nickname || ppd->modelname)
apple_conv_utf8(&p->make_model, ppd->lang_encoding);
#endif
ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_TEXT,
"printer-make-and-model", NULL, p->make_model);
if ((input_slot = ppdFindOption(ppd, "InputSlot")) != NULL)
num_media = input_slot->num_choices;
else
num_media = 0;
if ((media_type = ppdFindOption(ppd, "MediaType")) != NULL)
num_media += media_type->num_choices;
if ((page_size = ppdFindOption(ppd, "PageSize")) != NULL)
num_media += page_size->num_choices;
if ((media_quality = ppdFindOption(ppd, "EFMediaQualityMode")) != NULL)
num_media += media_quality->num_choices;
if (num_media == 0)
{
LogMessage(L_CRIT, "SetPrinterAttrs: The PPD file for printer %s "
"contains no media options and is therefore "
"invalid!", p->name);
}
else
{
attr = ippAddStrings(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
"media-supported", num_media, NULL, NULL);
if (attr != NULL)
{
val = attr->values;
if (input_slot != NULL)
for (i = 0; i < input_slot->num_choices; i ++, val ++)
val->string.text = strdup(input_slot->choices[i].choice);
if (media_type != NULL)
for (i = 0; i < media_type->num_choices; i ++, val ++)
val->string.text = strdup(media_type->choices[i].choice);
if (media_quality != NULL)
for (i = 0; i < media_quality->num_choices; i ++, val ++)
val->string.text = strdup(media_quality->choices[i].choice);
if (page_size != NULL)
{
for (i = 0; i < page_size->num_choices; i ++, val ++)
val->string.text = strdup(page_size->choices[i].choice);
ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "media-default",
NULL, page_size->defchoice);
}
else if (input_slot != NULL)
ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "media-default",
NULL, input_slot->defchoice);
else if (media_type != NULL)
ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "media-default",
NULL, media_type->defchoice);
else if (media_quality != NULL)
ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "media-default",
NULL, media_quality->defchoice);
else
ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "media-default",
NULL, "none");
}
}
if ((output_bin = ppdFindOption(ppd, "OutputBin")) != NULL)
{
attr = ippAddStrings(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
"output-bin-supported", output_bin->num_choices,
NULL, NULL);
if (attr != NULL)
{
for (i = 0, val = attr->values;
i < output_bin->num_choices;
i ++, val ++)
val->string.text = strdup(output_bin->choices[i].choice);
}
}
if (ppdFindOption(ppd, "Duplex") != NULL)
{
p->type |= CUPS_PRINTER_DUPLEX;
ippAddStrings(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "sides-supported",
3, NULL, sides);
ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "sides-default",
NULL, "one");
}
if (ppdFindOption(ppd, "Collate") != NULL)
p->type |= CUPS_PRINTER_COLLATE;
if (ppdFindOption(ppd, "StapleLocation") != NULL)
{
p->type |= CUPS_PRINTER_STAPLE;
finishings[num_finishings++] = IPP_FINISHINGS_STAPLE;
}
if (ppdFindOption(ppd, "BindEdge") != NULL)
{
p->type |= CUPS_PRINTER_BIND;
finishings[num_finishings++] = IPP_FINISHINGS_BIND;
}
for (i = 0; i < ppd->num_sizes; i ++)
if (ppd->sizes[i].length > 1728)
p->type |= CUPS_PRINTER_LARGE;
else if (ppd->sizes[i].length > 1008)
p->type |= CUPS_PRINTER_MEDIUM;
else
p->type |= CUPS_PRINTER_SMALL;
DEBUG_printf(("ppd->num_filters = %d\n", ppd->num_filters));
for (i = 0; i < ppd->num_filters; i ++)
{
DEBUG_printf(("ppd->filters[%d] = \"%s\"\n", i, ppd->filters[i]));
AddPrinterFilter(p, ppd->filters[i]);
}
if (ppd->num_filters == 0)
AddPrinterFilter(p, "application/vnd.cups-postscript 0 -");
ppdClose(ppd);
printer_type = p->type;
}
else if (access(filename, 0) == 0)
{
int pline;
ppd_status_t pstatus;
pstatus = ppdLastError(&pline);
LogMessage(L_ERROR, "PPD file for %s cannot be loaded!", p->name);
if (pstatus <= PPD_ALLOC_ERROR)
LogMessage(L_ERROR, "%s", strerror(errno));
else
LogMessage(L_ERROR, "%s on line %d.", ppdErrorString(pstatus),
pline);
LogMessage(L_INFO, "Hint: Run \"cupstestppd %s\" and fix any errors.",
filename);
AddPrinterFilter(p, "application/vnd.cups-postscript 0 -");
}
else
{
snprintf(filename, sizeof(filename), "%s/interfaces/%s", ServerRoot,
p->name);
if (access(filename, X_OK) == 0)
{
ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_TEXT,
"printer-make-and-model", NULL, "Local System V Printer");
snprintf(filename, sizeof(filename), "*/* 0 %s/interfaces/%s",
ServerRoot, p->name);
AddPrinterFilter(p, filename);
}
else if (p->device_uri &&
strncmp(p->device_uri, "ipp://", 6) == 0 &&
(strstr(p->device_uri, "/printers/") != NULL ||
strstr(p->device_uri, "/classes/") != NULL))
{
printer_type |= CUPS_PRINTER_REMOTE;
attr = ippFindAttribute(p->attrs, "printer-uri-supported", IPP_TAG_URI);
free(attr->values[0].string.text);
attr->values[0].string.text = strdup(p->device_uri);
ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_TEXT,
"printer-make-and-model", NULL, "Remote Printer");
p->raw = 1;
}
else
{
ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_TEXT,
"printer-make-and-model", NULL, "Local Raw Printer");
p->raw = 1;
}
}
ippAddIntegers(p->attrs, IPP_TAG_PRINTER, IPP_TAG_ENUM,
"finishings-supported", num_finishings, (int *)finishings);
ippAddInteger(p->attrs, IPP_TAG_PRINTER, IPP_TAG_ENUM,
"finishings-default", IPP_FINISHINGS_NONE);
}
}
#ifdef __APPLE__
SetMimeTypesAttr(p);
#endif
ippAddInteger(p->attrs, IPP_TAG_PRINTER, IPP_TAG_ENUM, "printer-type",
printer_type);
DEBUG_printf(("SetPrinterAttrs: leaving name = %s, type = %x\n", p->name,
p->type));
#ifdef __sgi
write_irix_config(p);
write_irix_state(p);
#endif
}
void
SetPrinterReasons(printer_t *p,
const char *s)
{
int i;
const char *sptr;
char reason[255],
*rptr;
if (s[0] == '-' || s[0] == '+')
{
sptr = s + 1;
}
else
{
sptr = s;
for (i = 0; i < p->num_reasons; i ++)
free(p->reasons[i]);
p->num_reasons = 0;
}
while (*sptr)
{
while (isspace(*sptr) || *sptr == ',')
sptr ++;
for (rptr = reason; *sptr && !isspace(*sptr) && *sptr != ','; sptr ++)
if (rptr < (reason + sizeof(reason) - 1))
*rptr++ = *sptr;
if (rptr == reason)
break;
*rptr = '\0';
if (s[0] == '-')
{
for (i = 0; i < p->num_reasons; i ++)
if (!strcasecmp(reason, p->reasons[i]))
{
p->num_reasons --;
free(p->reasons[i]);
if (i < p->num_reasons)
memmove(p->reasons + i, p->reasons + i + 1,
(p->num_reasons - i) * sizeof(char *));
i --;
}
}
else if (s[0] == '+' &&
p->num_reasons < (int)(sizeof(p->reasons) / sizeof(p->reasons[0])))
{
for (i = 0; i < p->num_reasons; i ++)
if (!strcasecmp(reason, p->reasons[i]))
break;
if (i >= p->num_reasons)
{
p->reasons[i] = strdup(reason);
p->num_reasons ++;
}
}
}
}
void
SetPrinterState(printer_t *p,
ipp_pstate_t s,
int update)
{
ipp_pstate_t old_state;
if (p->type & CUPS_PRINTER_REMOTE)
return;
old_state = p->state;
p->state = s;
if (old_state != s)
{
p->state_time = time(NULL);
p->browse_time = 0;
#ifdef __sgi
write_irix_state(p);
#endif
}
AddPrinterHistory(p);
if ((old_state == IPP_PRINTER_STOPPED) != (s == IPP_PRINTER_STOPPED) &&
update)
{
if (p->type & CUPS_PRINTER_CLASS)
SaveAllClasses();
else
SaveAllPrinters();
}
}
void
SortPrinters(void)
{
printer_t *current,
*prev,
*next;
int did_swap;
do
{
for (did_swap = 0, current = Printers, prev = NULL; current != NULL;)
if (current->next == NULL)
break;
else if (strcasecmp(current->name, current->next->name) > 0)
{
DEBUG_printf(("Swapping %s and %s...\n", current->name,
current->next->name));
did_swap = 1;
if (prev == NULL)
Printers = current->next;
else
prev->next = current->next;
next = current->next;
current->next = next->next;
next->next = current;
prev = next;
}
else
{
prev = current;
current = current->next;
}
}
while (did_swap);
}
void
StopPrinter(printer_t *p,
int update)
{
job_t *job;
SetPrinterState(p, IPP_PRINTER_STOPPED, update);
if (p->job)
{
job = (job_t *)p->job;
StopJob(job->id, 0);
job->state->values[0].integer = IPP_JOB_PENDING;
SaveJob(job->id);
}
}
const char *
ValidateDest(const char *hostname,
const char *resource,
cups_ptype_t *dtype)
{
printer_t *p;
char localname[1024],
*lptr,
*sptr;
DEBUG_printf(("ValidateDest(\"%s\", \"%s\", %p)\n", hostname, resource, dtype));
if (strncmp(resource, "/classes/", 9) == 0)
{
resource += 9;
}
else if (strncmp(resource, "/printers/", 10) == 0)
{
resource += 10;
}
else
{
return (NULL);
}
if ((p = FindPrinter(resource)) == NULL)
p = FindClass(resource);
if (p == NULL && strchr(resource, '@') == NULL)
return (NULL);
else if (p != NULL)
{
*dtype = p->type & (CUPS_PRINTER_CLASS | CUPS_PRINTER_IMPLICIT |
CUPS_PRINTER_REMOTE);
return (p->name);
}
if (strcasecmp(hostname, "localhost") == 0)
hostname = ServerName;
strlcpy(localname, hostname, sizeof(localname));
if (strcasecmp(hostname, ServerName) != 0)
{
lptr = strchr(localname, '.');
sptr = strchr(ServerName, '.');
if (sptr != NULL && lptr != NULL)
{
while (lptr != NULL)
{
if (strcasecmp(lptr, sptr) == 0)
{
*lptr = '\0';
break;
}
else
lptr = strchr(lptr + 1, '.');
}
}
}
DEBUG_printf(("localized hostname is \"%s\"...\n", localname));
for (p = Printers; p != NULL; p = p->next)
if (strcasecmp(p->hostname, localname) == 0 &&
strcasecmp(p->name, resource) == 0)
{
*dtype = p->type & (CUPS_PRINTER_CLASS | CUPS_PRINTER_IMPLICIT |
CUPS_PRINTER_REMOTE);
return (p->name);
}
return (NULL);
}
void
WritePrintcap(void)
{
cups_file_t *fp;
printer_t *p;
#ifdef __sgi
write_irix_state(DefaultPrinter);
#endif
if (!Printcap[0])
return;
if ((fp = cupsFileOpen(Printcap, "w")) == NULL)
return;
cupsFilePuts(fp, "# This file was automatically generated by cupsd(8) from the\n");
cupsFilePrintf(fp, "# %s/printers.conf file. All changes to this file\n",
ServerRoot);
cupsFilePuts(fp, "# will be lost.\n");
switch (PrintcapFormat)
{
case PRINTCAP_BSD:
if (DefaultPrinter)
cupsFilePrintf(fp, "%s|%s:rm=%s:rp=%s:\n", DefaultPrinter->name,
DefaultPrinter->info, ServerName, DefaultPrinter->name);
for (p = Printers; p != NULL; p = p->next)
if (p != DefaultPrinter)
cupsFilePrintf(fp, "%s|%s:rm=%s:rp=%s:\n", p->name, p->info,
ServerName, p->name);
break;
case PRINTCAP_SOLARIS:
cupsFilePuts(fp, "_all:all=");
for (p = Printers; p != NULL; p = p->next)
cupsFilePrintf(fp, "%s%c", p->name, p->next ? ',' : '\n');
if (DefaultPrinter)
cupsFilePrintf(fp, "_default:use=%s\n", DefaultPrinter->name);
for (p = Printers; p != NULL; p = p->next)
cupsFilePrintf(fp, "%s:\\\n"
"\t:bsdaddr=%s,%s:\\\n"
"\t:description=%s:\n",
p->name, ServerName, p->name, p->info ? p->info : "");
break;
}
cupsFileClose(fp);
}
#ifdef __APPLE__
static void
SetMimeTypesAttr(printer_t *p)
{
int i;
int numPrinterMimeTypes;
const char **printerMimeTypes;
char type[MIME_MAX_SUPER + MIME_MAX_TYPE + 2];
int num_filters;
mime_filter_t *filters;
printerMimeTypes = calloc(MimeDatabase->num_types + 1, sizeof(const char *));
if (printerMimeTypes)
{
for (i = numPrinterMimeTypes = 0; i < MimeDatabase->num_types; i ++)
{
filters = mimeFilter(MimeDatabase, MimeDatabase->types[i], p->filetype, &num_filters, MAX_FILTERS - 1);
if (num_filters != 0)
{
snprintf(type, sizeof(type), "%s/%s", MimeDatabase->types[i]->super, MimeDatabase->types[i]->type);
printerMimeTypes[numPrinterMimeTypes++] = strdup(type);
}
if (filters != NULL)
free(filters);
}
if (!mimeType(MimeDatabase, "application", "octet-stream"))
printerMimeTypes[numPrinterMimeTypes++] = strdup("application/octet-stream");
ippAddStrings(p->attrs, IPP_TAG_PRINTER,
(ipp_tag_t)IPP_TAG_MIMETYPE,
"document-format-supported", numPrinterMimeTypes, NULL, printerMimeTypes);
for (i = 0; i < numPrinterMimeTypes; i ++)
free((void *)printerMimeTypes[i]);
free(printerMimeTypes);
}
return;
}
#endif
#ifdef __sgi
static void
write_irix_config(printer_t *p)
{
char filename[1024];
cups_file_t *fp;
ipp_attribute_t *attr;
snprintf(filename, sizeof(filename), "/var/spool/lp/interface/%s", p->name);
if (p->type & CUPS_PRINTER_CLASS)
unlink(filename);
else if ((fp = cupsFileOpen(filename, "w")) != NULL)
{
cupsFilePuts(fp, "#!/bin/sh\n");
if ((attr = ippFindAttribute(p->attrs, "printer-make-and-model",
IPP_TAG_TEXT)) != NULL)
cupsFilePrintf(fp, "NAME=\"%s\"\n", attr->values[0].string.text);
else if (p->type & CUPS_PRINTER_CLASS)
cupsFilePuts(fp, "NAME=\"Printer Class\"\n");
else
cupsFilePuts(fp, "NAME=\"Remote Destination\"\n");
if (p->type & CUPS_PRINTER_COLOR)
cupsFilePuts(fp, "TYPE=ColorPostScript\n");
else
cupsFilePuts(fp, "TYPE=MonoPostScript\n");
cupsFilePrintf(fp, "HOSTNAME=%s\n", ServerName);
cupsFilePrintf(fp, "HOSTPRINTER=%s\n", p->name);
cupsFileClose(fp);
chmod(filename, 0755);
chown(filename, User, Group);
}
snprintf(filename, sizeof(filename), "/var/spool/lp/member/%s", p->name);
if (p->type & CUPS_PRINTER_CLASS)
unlink(filename);
else if ((fp = cupsFileOpen(filename, "w")) != NULL)
{
cupsFilePuts(fp, "/dev/null\n");
cupsFileClose(fp);
chmod(filename, 0644);
chown(filename, User, Group);
}
snprintf(filename, sizeof(filename), "/var/spool/lp/gui_interface/ELF/%s.gui", p->name);
if (p->type & CUPS_PRINTER_CLASS)
unlink(filename);
else if ((fp = cupsFileOpen(filename, "w")) != NULL)
{
cupsFilePuts(fp, "#!/bin/sh\n");
cupsFilePrintf(fp, "%s -d %s -o \"$3\"\n", PrintcapGUI, p->name);
cupsFileClose(fp);
chmod(filename, 0755);
chown(filename, User, Group);
}
snprintf(filename, sizeof(filename), "/var/spool/lp/pod/%s.config", p->name);
if (p->type & CUPS_PRINTER_CLASS)
unlink(filename);
else if ((fp = cupsFileOpen(filename, "w")) != NULL)
{
cupsFilePrintf(fp, "Printer Class | %s\n",
(p->type & CUPS_PRINTER_COLOR) ? "ColorPostScript" : "MonoPostScript");
cupsFilePrintf(fp, "Printer Model | %s\n", p->make_model ? p->make_model : "");
cupsFilePrintf(fp, "Location Code | %s\n", p->location ? p->location : "");
cupsFilePrintf(fp, "Physical Location | %s\n", p->info ? p->info : "");
cupsFilePrintf(fp, "Port Path | %s\n", p->device_uri ? p->device_uri : "");
cupsFilePrintf(fp, "Config Path | /var/spool/lp/pod/%s.config\n", p->name);
cupsFilePrintf(fp, "Active Status Path | /var/spool/lp/pod/%s.status\n", p->name);
cupsFilePuts(fp, "Status Update Wait | 10 seconds\n");
cupsFileClose(fp);
chmod(filename, 0664);
chown(filename, User, Group);
}
}
static void
write_irix_state(printer_t *p)
{
char filename[1024];
cups_file_t *fp;
int tag;
if (p)
{
snprintf(filename, sizeof(filename), "/var/spool/lp/pod/%s.status", p->name);
if (p->type & CUPS_PRINTER_CLASS)
unlink(filename);
else if ((fp = cupsFileOpen(filename, "w")) != NULL)
{
cupsFilePrintf(fp, "Operational Status | %s\n",
(p->state == IPP_PRINTER_IDLE) ? "Idle" :
(p->state == IPP_PRINTER_PROCESSING) ? "Busy" :
"Faulted");
cupsFilePrintf(fp, "Information | 01 00 00 | %s\n", CUPS_SVERSION);
cupsFilePrintf(fp, "Information | 02 00 00 | Device URI: %s\n",
p->device_uri ? p->device_uri : "");
cupsFilePrintf(fp, "Information | 03 00 00 | %s jobs\n",
p->accepting ? "Accepting" : "Not accepting");
cupsFilePrintf(fp, "Information | 04 00 00 | %s\n", p->state_message);
cupsFileClose(fp);
chmod(filename, 0664);
chown(filename, User, Group);
}
snprintf(filename, sizeof(filename), "/var/spool/lp/activeicons/%s", p->name);
if (p->type & CUPS_PRINTER_CLASS)
unlink(filename);
else if ((fp = cupsFileOpen(filename, "w")) != NULL)
{
if (p->type & CUPS_PRINTER_COLOR)
tag = 66240;
else
tag = 66272;
if (p->type & CUPS_PRINTER_REMOTE)
tag |= 8;
if (p->state == IPP_PRINTER_PROCESSING)
tag |= 1;
else if (p->state == IPP_PRINTER_STOPPED)
tag |= 2;
cupsFilePuts(fp, "#!/bin/sh\n");
cupsFilePrintf(fp, "#Tag %d\n", tag);
cupsFileClose(fp);
chmod(filename, 0755);
chown(filename, User, Group);
}
}
snprintf(filename, sizeof(filename), "/var/spool/lp/default");
if (DefaultPrinter != NULL)
{
if ((fp = cupsFileOpen(filename, "w")) != NULL)
{
cupsFilePrintf(fp, "%s\n", DefaultPrinter->name);
cupsFileClose(fp);
chmod(filename, 0644);
chown(filename, User, Group);
}
}
else
unlink(filename);
}
#endif
#ifdef __APPLE__
static void
apple_conv_utf8(char **str,
const char *encoding)
{
int i;
CFStringRef cfStrRef;
CFStringEncoding cfStrEncoding;
char utf8_str[IPP_MAX_NAME];
const char *utf8_str_ptr;
static struct
{
const char * const str;
CFStringEncoding cfStrEncoding;
} apple_lang_encoding[] =
{
{ "ISOLatin1", kCFStringEncodingISOLatin1 },
{ "JIS83-RKSJ", kCFStringEncodingMacJapanese },
{ "WindowsANSI", kCFStringEncodingWindowsLatin1 },
{ "UTF-8", kCFStringEncodingUTF8 },
{ "UTF8", kCFStringEncodingUTF8 }
};
cfStrEncoding = kCFStringEncodingMacRoman;
if (encoding != NULL)
{
for (i=0; i < sizeof(apple_lang_encoding)/sizeof(apple_lang_encoding[0]); i++)
{
if (strcmp(encoding, apple_lang_encoding[i].str) == 0)
{
cfStrEncoding = apple_lang_encoding[i].cfStrEncoding;
break;
}
}
}
if (cfStrEncoding != kCFStringEncodingUTF8)
{
cfStrRef = CFStringCreateWithCString(kCFAllocatorDefault, *str, cfStrEncoding);
if (cfStrRef != NULL)
{
utf8_str_ptr = CFStringGetCStringPtr(cfStrRef, kCFStringEncodingUTF8);
if (utf8_str_ptr == NULL)
{
if (CFStringGetCString(cfStrRef, utf8_str, sizeof(utf8_str), kCFStringEncodingUTF8) != 0)
utf8_str_ptr = utf8_str;
}
if (utf8_str_ptr != NULL)
SetString(str, utf8_str_ptr);
CFRelease(cfStrRef);
}
}
}
#endif