/*
- * "$Id: admin.c 4943 2006-01-18 20:30:42Z mike $"
+ * Administration CGI for CUPS.
*
- * Administration CGI for the Common UNIX Printing System (CUPS).
+ * Copyright © 2007-2019 by Apple Inc.
+ * Copyright © 1997-2007 by Easy Software Products.
*
- * Copyright 1997-2006 by Easy Software Products.
- *
- * These coded instructions, statements, and computer programs are the
- * property of Easy Software Products and are protected by Federal
- * copyright law. Distribution and use rights are outlined in the file
- * "LICENSE.txt" which should have been included with this file. If this
- * file is missing or damaged please contact Easy Software Products
- * at:
- *
- * Attn: CUPS Licensing Information
- * Easy Software Products
- * 44141 Airport View Drive, Suite 204
- * Hollywood, Maryland 20636 USA
- *
- * Voice: (301) 373-9600
- * EMail: cups-info@cups.org
- * WWW: http://www.cups.org
- *
- * Contents:
- *
- * main() - Main entry for CGI.
- * do_am_class() - Add or modify a class.
- * do_am_printer() - Add or modify a printer.
- * do_config_printer() - Configure the default options for a printer.
- * do_config_server() - Configure server settings.
- * do_delete_class() - Delete a class...
- * do_delete_printer() - Delete a printer...
- * do_export() - Export printers to Samba...
- * do_menu() - Show the main menu...
- * do_printer_op() - Do a printer operation.
- * do_set_allowed_users() - Set the allowed/denied users for a queue.
- * do_set_sharing() - Set printer-is-shared value...
- * match_string() - Return the number of matching characters.
+ * Licensed under Apache License v2.0. See the file "LICENSE" for more
+ * information.
*/
/*
*/
#include "cgi-private.h"
-#include <cups/file.h>
+#include <cups/http-private.h>
+#include <cups/ppd-private.h>
+#include <cups/adminutil.h>
+#include <cups/ppd.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/wait.h>
+#include <limits.h>
+
+
+/*
+ * Local globals...
+ */
+
+static int current_device = 0; /* Current device shown */
/*
* Local functions...
*/
+static void choose_device_cb(const char *device_class, const char *device_id, const char *device_info, const char *device_make_and_model, const char *device_uri, const char *device_location, const char *title);
static void do_am_class(http_t *http, int modify);
static void do_am_printer(http_t *http, int modify);
-static void do_config_printer(http_t *http);
static void do_config_server(http_t *http);
static void do_delete_class(http_t *http);
static void do_delete_printer(http_t *http);
-static void do_export(http_t *http);
+static void do_list_printers(http_t *http);
static void do_menu(http_t *http);
-static void do_printer_op(http_t *http,
- ipp_op_t op, const char *title);
static void do_set_allowed_users(http_t *http);
+static void do_set_default(http_t *http);
+static void do_set_options(http_t *http, int is_class);
static void do_set_sharing(http_t *http);
-static int match_string(const char *a, const char *b);
+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 char *get_printer_ppd(const char *uri, char *buffer, size_t bufsize);
/*
*/
int /* O - Exit status */
-main(int argc, /* I - Number of command-line arguments */
- char *argv[]) /* I - Command-line arguments */
+main(void)
{
http_t *http; /* Connection to the server */
const char *op; /* Operation name */
* Connect to the HTTP server...
*/
+ fputs("DEBUG: admin.cgi started...\n", stderr);
+
http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption());
+ if (!http)
+ {
+ perror("ERROR: Unable to connect to cupsd");
+ fprintf(stderr, "DEBUG: cupsServer()=\"%s\"\n",
+ cupsServer() ? cupsServer() : "(null)");
+ fprintf(stderr, "DEBUG: ippPort()=%d\n", ippPort());
+ fprintf(stderr, "DEBUG: cupsEncryption()=%d\n", cupsEncryption());
+ exit(1);
+ }
+
+ fprintf(stderr, "DEBUG: http=%p\n", http);
+
/*
* Set the web interface section...
*/
cgiSetVariable("SECTION", "admin");
+ cgiSetVariable("REFRESH_PAGE", "");
/*
* See if we have form data...
*/
- if (!cgiInitialize())
+ if (!cgiInitialize() || !cgiGetVariable("OP"))
{
/*
* Nope, send the administration menu...
*/
+ fputs("DEBUG: No form data, showing main menu...\n", stderr);
+
do_menu(http);
}
- else if ((op = cgiGetVariable("OP")) != NULL)
+ else if ((op = cgiGetVariable("OP")) != NULL && cgiIsPOST())
{
/*
* Do the operation...
*/
- if (!strcmp(op, "redirect"))
- {
- const char *url; /* Redirection URL... */
-
+ fprintf(stderr, "DEBUG: op=\"%s\"...\n", op);
- if ((url = cgiGetVariable("URL")) != NULL)
- printf("Location: %s\n\n", url);
+ if (!*op)
+ {
+ const char *printer = getenv("PRINTER_NAME"),
+ /* Printer or class name */
+ *server_port = getenv("SERVER_PORT");
+ /* Port number string */
+ int port = atoi(server_port ? server_port : "0");
+ /* Port number */
+ char uri[1024]; /* URL */
+
+ if (printer)
+ httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri),
+ getenv("HTTPS") ? "https" : "http", NULL,
+ getenv("SERVER_NAME"), port, "/%s/%s",
+ cgiGetVariable("IS_CLASS") ? "classes" : "printers",
+ printer);
else
- puts("Location: /admin\n");
- }
- else if (!strcmp(op, "start-printer"))
- do_printer_op(http, IPP_RESUME_PRINTER, cgiText(_("Start Printer")));
- else if (!strcmp(op, "stop-printer"))
- do_printer_op(http, IPP_PAUSE_PRINTER, cgiText(_("Stop Printer")));
- else if (!strcmp(op, "start-class"))
- do_printer_op(http, IPP_RESUME_PRINTER, cgiText(_("Start Class")));
- else if (!strcmp(op, "stop-class"))
- do_printer_op(http, IPP_PAUSE_PRINTER, cgiText(_("Stop Class")));
- else if (!strcmp(op, "accept-jobs"))
- do_printer_op(http, CUPS_ACCEPT_JOBS, cgiText(_("Accept Jobs")));
- else if (!strcmp(op, "reject-jobs"))
- do_printer_op(http, CUPS_REJECT_JOBS, cgiText(_("Reject Jobs")));
- else if (!strcmp(op, "purge-jobs"))
- do_printer_op(http, IPP_PURGE_JOBS, cgiText(_("Purge Jobs")));
+ httpAssembleURI(HTTP_URI_CODING_ALL, uri, sizeof(uri),
+ getenv("HTTPS") ? "https" : "http", NULL,
+ getenv("SERVER_NAME"), port, "/admin");
+
+ printf("Location: %s\n\n", uri);
+ }
else if (!strcmp(op, "set-allowed-users"))
do_set_allowed_users(http);
else if (!strcmp(op, "set-as-default"))
- do_printer_op(http, CUPS_SET_DEFAULT, cgiText(_("Set As Default")));
+ do_set_default(http);
else if (!strcmp(op, "set-sharing"))
do_set_sharing(http);
+ else if (!strcmp(op, "find-new-printers") ||
+ !strcmp(op, "list-available-printers"))
+ do_list_printers(http);
else if (!strcmp(op, "add-class"))
do_am_class(http, 0);
else if (!strcmp(op, "add-printer"))
do_delete_class(http);
else if (!strcmp(op, "delete-printer"))
do_delete_printer(http);
+ else if (!strcmp(op, "set-class-options"))
+ do_set_options(http, 1);
else if (!strcmp(op, "set-printer-options"))
- do_config_printer(http);
+ do_set_options(http, 0);
else if (!strcmp(op, "config-server"))
do_config_server(http);
- else if (!strcmp(op, "export-samba"))
- do_export(http);
else
{
/*
- * Bad operation code... Display an error...
+ * Bad operation code - display an error...
*/
cgiStartHTML(cgiText(_("Administration")));
cgiEndHTML();
}
}
+ else if (op && !strcmp(op, "redirect"))
+ {
+ const char *url; /* Redirection URL... */
+ char prefix[1024]; /* URL prefix */
+
+
+ if (getenv("HTTPS"))
+ snprintf(prefix, sizeof(prefix), "https://%s:%s",
+ getenv("SERVER_NAME"), getenv("SERVER_PORT"));
+ else
+ snprintf(prefix, sizeof(prefix), "http://%s:%s",
+ getenv("SERVER_NAME"), getenv("SERVER_PORT"));
+
+ fprintf(stderr, "DEBUG: redirecting with prefix %s!\n", prefix);
+
+ if ((url = cgiGetVariable("URL")) != NULL)
+ {
+ char encoded[1024], /* Encoded URL string */
+ *ptr; /* Pointer into encoded string */
+
+
+ ptr = encoded;
+ if (*url != '/')
+ *ptr++ = '/';
+
+ for (; *url && ptr < (encoded + sizeof(encoded) - 4); url ++)
+ {
+ if (strchr("%@&+ <>#=", *url) || *url < ' ' || *url & 128)
+ {
+ /*
+ * Percent-encode this character; safe because we have at least 4
+ * bytes left in the array...
+ */
+
+ sprintf(ptr, "%%%02X", *url & 255);
+ ptr += 3;
+ }
+ else
+ *ptr++ = *url;
+ }
+
+ *ptr = '\0';
+
+ if (*url)
+ {
+ /*
+ * URL was too long, just redirect to the admin page...
+ */
+
+ printf("Location: %s/admin\n\n", prefix);
+ }
+ else
+ {
+ /*
+ * URL is OK, redirect there...
+ */
+
+ printf("Location: %s%s\n\n", prefix, encoded);
+ }
+ }
+ else
+ printf("Location: %s/admin\n\n", prefix);
+ }
else
{
/*
- * Form data but no operation code... Display an error...
+ * Form data but no operation code - display an error...
*/
cgiStartHTML(cgiText(_("Administration")));
}
+/*
+ * 'choose_device_cb()' - Add a device to the device selection page.
+ */
+
+static void
+choose_device_cb(
+ const char *device_class, /* I - Class */
+ const char *device_id, /* I - 1284 device ID */
+ const char *device_info, /* I - Description */
+ const char *device_make_and_model, /* I - Make and model */
+ const char *device_uri, /* I - Device URI */
+ const char *device_location, /* I - Location */
+ const char *title) /* I - Page title */
+{
+ /*
+ * For modern browsers, start a multi-part page so we can show that something
+ * is happening. Non-modern browsers just get everything at the end...
+ */
+
+ if (current_device == 0 && cgiSupportsMultipart())
+ {
+ cgiStartMultipart();
+ cgiStartHTML(title);
+ cgiCopyTemplateLang("choose-device.tmpl");
+ cgiEndHTML();
+ fflush(stdout);
+ }
+
+
+ /*
+ * Add the device to the array...
+ */
+
+ cgiSetArray("device_class", current_device, device_class);
+ cgiSetArray("device_id", current_device, device_id);
+ cgiSetArray("device_info", current_device, device_info);
+ cgiSetArray("device_make_and_model", current_device, device_make_and_model);
+ cgiSetArray("device_uri", current_device, device_uri);
+ cgiSetArray("device_location", current_device, device_location);
+
+ current_device ++;
+}
+
+
/*
* 'do_am_class()' - Add or modify a class.
*/
ipp_attribute_t *attr; /* member-uris attribute */
char uri[HTTP_MAX_URI]; /* Device or printer URI */
const char *name, /* Pointer to class name */
+ *op, /* Operation name */
*ptr; /* Pointer to CGI variable */
const char *title; /* Title of page */
static const char * const pattrs[] = /* Requested printer attributes */
title = cgiText(modify ? _("Modify Class") : _("Add Class"));
+ op = cgiGetVariable("OP");
name = cgiGetVariable("PRINTER_NAME");
if (cgiGetVariable("PRINTER_LOCATION") == NULL)
*
* attributes-charset
* attributes-natural-language
- * printer-uri
*/
request = ippNewRequest(CUPS_GET_PRINTERS);
- ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
- NULL, "ipp://localhost/printers");
+ ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_ENUM, "printer-type",
+ CUPS_PRINTER_LOCAL);
+ ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_ENUM, "printer-type-mask",
+ CUPS_PRINTER_CLASS | CUPS_PRINTER_REMOTE);
/*
* Do the request and get back a response...
*/
+ cgiClearVariables();
+ if (op)
+ cgiSetVariable("OP", op);
+ if (name)
+ cgiSetVariable("PRINTER_NAME", name);
+
if ((response = cupsDoRequest(http, request, "/")) != NULL)
{
/*
if (attr->name && !strcmp(attr->name, "printer-uri-supported"))
{
if ((ptr = strrchr(attr->values[0].string.text, '/')) != NULL &&
- (!name || strcasecmp(name, ptr + 1)))
+ (!name || _cups_strcasecmp(name, ptr + 1)))
{
/*
* Don't show the current class...
attr = attr->next)
if (attr->name && !strcmp(attr->name, "printer-name"))
{
- if (!name || strcasecmp(name, attr->values[0].string.text))
+ if (!name || _cups_strcasecmp(name, attr->values[0].string.text))
{
/*
* Don't show the current class...
request = ippNewRequest(IPP_GET_PRINTER_ATTRIBUTES);
- httpAssembleURIf(uri, sizeof(uri), "ipp", NULL, "localhost", 0,
- "/classes/%s", name);
+ httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
+ "localhost", 0, "/classes/%s", name);
ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
NULL, uri);
if ((response = cupsDoRequest(http, request, "/")) != NULL)
{
- if ((attr = ippFindAttribute(response, "member-names", IPP_TAG_NAME)) != NULL)
+ if ((attr = ippFindAttribute(response, "member-names",
+ IPP_TAG_NAME)) != NULL)
{
/*
* Mark any current members in the class...
{
for (j = 0; j < num_printers; j ++)
{
- if (!strcasecmp(attr->values[i].string.text,
+ if (!_cups_strcasecmp(attr->values[i].string.text,
cgiGetArray("MEMBER_NAMES", j)))
{
cgiSetArray("MEMBER_SELECTED", j, "SELECTED");
return;
}
+ if (!name)
+ {
+ cgiStartHTML(title);
+ cgiSetVariable("ERROR", cgiText(_("Missing form variable")));
+ cgiCopyTemplateLang("error.tmpl");
+ cgiEndHTML();
+ return;
+ }
+
for (ptr = name; *ptr; ptr ++)
if ((*ptr >= 0 && *ptr <= ' ') || *ptr == 127 || *ptr == '/' || *ptr == '#')
break;
request = ippNewRequest(CUPS_ADD_CLASS);
- httpAssembleURIf(uri, sizeof(uri), "ipp", NULL, "localhost", 0,
- "/classes/%s", cgiGetVariable("PRINTER_NAME"));
+ httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
+ "localhost", 0, "/classes/%s", name);
ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
NULL, uri);
attr = ippAddStrings(request, IPP_TAG_PRINTER, IPP_TAG_URI, "member-uris",
num_printers, NULL, NULL);
for (i = 0; i < num_printers; i ++)
- attr->values[i].string.text = strdup(cgiGetArray("MEMBER_URIS", i));
+ ippSetString(request, &attr, i, cgiGetArray("MEMBER_URIS", i));
}
/*
ippDelete(cupsDoRequest(http, request, "/admin/"));
- if (cupsLastError() > IPP_OK_CONFLICT)
+ if (cupsLastError() == IPP_NOT_AUTHORIZED)
+ {
+ puts("Status: 401\n");
+ exit(0);
+ }
+ else if (cupsLastError() > IPP_OK_CONFLICT)
{
cgiStartHTML(title);
- cgiShowIPPError(modify ? _("Unable to modify class:") :
- _("Unable to add class:"));
+ cgiShowIPPError(modify ? _("Unable to modify class") :
+ _("Unable to add class"));
}
else
{
char refresh[1024]; /* Refresh URL */
cgiFormEncode(uri, name, sizeof(uri));
- snprintf(refresh, sizeof(refresh), "5;/admin/?OP=redirect&URL=/classes/%s",
+ snprintf(refresh, sizeof(refresh), "5;URL=/admin/?OP=redirect&URL=/classes/%s",
uri);
cgiSetVariable("refresh_page", refresh);
int modify) /* I - Modify the printer? */
{
int i; /* Looping var */
- int element; /* Element number */
- ipp_attribute_t *attr, /* Current attribute */
- *last; /* Last attribute */
+ ipp_attribute_t *attr; /* Current attribute */
ipp_t *request, /* IPP request */
*response, /* IPP response */
*oldinfo; /* Old printer information */
const cgi_file_t *file; /* Uploaded file, if any */
const char *var; /* CGI variable */
char uri[HTTP_MAX_URI], /* Device or printer URI */
- *uriptr; /* Pointer into URI */
+ *uriptr, /* Pointer into URI */
+ evefile[1024] = ""; /* IPP Everywhere PPD file */
int maxrate; /* Maximum baud rate */
char baudrate[255]; /* Baud rate string */
const char *name, /* Pointer to class name */
};
+ ptr = cgiGetVariable("DEVICE_URI");
fprintf(stderr, "DEBUG: do_am_printer: DEVICE_URI=\"%s\"\n",
- cgiGetVariable("DEVICE_URI"));
+ ptr ? ptr : "(null)");
title = cgiText(modify ? _("Modify Printer") : _("Add Printer"));
request = ippNewRequest(IPP_GET_PRINTER_ATTRIBUTES);
- httpAssembleURIf(uri, sizeof(uri), "ipp", NULL, "localhost", 0,
- "/printers/%s", cgiGetVariable("PRINTER_NAME"));
+ httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
+ "localhost", 0, "/printers/%s",
+ cgiGetVariable("PRINTER_NAME"));
ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
NULL, uri);
else
oldinfo = NULL;
- if ((name = cgiGetVariable("PRINTER_NAME")) == NULL ||
- cgiGetVariable("PRINTER_LOCATION") == NULL)
- {
- cgiStartHTML(title);
+ file = cgiGetFile();
- if (modify)
- {
- /*
- * Update the location and description of an existing printer...
- */
+ if (file)
+ {
+ fprintf(stderr, "DEBUG: file->tempfile=%s\n", file->tempfile);
+ fprintf(stderr, "DEBUG: file->name=%s\n", file->name);
+ fprintf(stderr, "DEBUG: file->filename=%s\n", file->filename);
+ fprintf(stderr, "DEBUG: file->mimetype=%s\n", file->mimetype);
+ }
- if (oldinfo)
- cgiSetIPPVars(oldinfo, NULL, NULL, NULL, 0);
+ if ((name = cgiGetVariable("PRINTER_NAME")) != NULL)
+ {
+ for (ptr = name; *ptr; ptr ++)
+ if ((*ptr >= 0 && *ptr <= ' ') || *ptr == 127 || *ptr == '/' || *ptr == '\\' || *ptr == '?' || *ptr == '\'' || *ptr == '\"' || *ptr == '#')
+ break;
- cgiCopyTemplateLang("modify-printer.tmpl");
+ if (*ptr || ptr == name || strlen(name) > 127)
+ {
+ cgiSetVariable("ERROR",
+ cgiText(_("The printer name may only contain up to 127 printable characters and may not contain spaces, slashes (/ \\), quotes (' \"), question mark (?), or the pound sign (#).")));
+ cgiStartHTML(title);
+ cgiCopyTemplateLang("error.tmpl");
+ cgiEndHTML();
+ return;
}
- else
+ }
+
+ if ((var = cgiGetVariable("DEVICE_URI")) != NULL)
+ {
+ if ((uriptr = strrchr(var, '|')) != NULL)
{
/*
- * Get the name, location, and description for a new printer...
+ * Extract make and make/model from device URI string...
*/
- cgiCopyTemplateLang("add-printer.tmpl");
- }
-
- cgiEndHTML();
-
- if (oldinfo)
- ippDelete(oldinfo);
-
- return;
- }
+ char make[1024], /* Make string */
+ *makeptr; /* Pointer into make */
- for (ptr = name; *ptr; ptr ++)
- if ((*ptr >= 0 && *ptr <= ' ') || *ptr == 127 || *ptr == '/' || *ptr == '#')
- break;
- if (*ptr || ptr == name || strlen(name) > 127)
- {
- cgiSetVariable("ERROR",
- cgiText(_("The printer name may only contain up to "
- "127 printable characters and may not "
- "contain spaces, slashes (/), or the "
- "pound sign (#).")));
- cgiStartHTML(title);
- cgiCopyTemplateLang("error.tmpl");
- cgiEndHTML();
- return;
- }
+ *uriptr++ = '\0';
- file = cgiGetFile();
+ strlcpy(make, uriptr, sizeof(make));
- if (file)
- {
- fprintf(stderr, "DEBUG: file->tempfile=%s\n", file->tempfile);
- fprintf(stderr, "DEBUG: file->name=%s\n", file->name);
- fprintf(stderr, "DEBUG: file->filename=%s\n", file->filename);
- fprintf(stderr, "DEBUG: file->mimetype=%s\n", file->mimetype);
- }
+ if ((makeptr = strchr(make, ' ')) != NULL)
+ *makeptr = '\0';
+ else if ((makeptr = strchr(make, '-')) != NULL)
+ *makeptr = '\0';
+ else if (!_cups_strncasecmp(make, "laserjet", 8) ||
+ !_cups_strncasecmp(make, "deskjet", 7) ||
+ !_cups_strncasecmp(make, "designjet", 9))
+ strlcpy(make, "HP", sizeof(make));
+ else if (!_cups_strncasecmp(make, "phaser", 6))
+ strlcpy(make, "Xerox", sizeof(make));
+ else if (!_cups_strncasecmp(make, "stylus", 6))
+ strlcpy(make, "Epson", sizeof(make));
+ else
+ strlcpy(make, "Generic", sizeof(make));
- if ((var = cgiGetVariable("DEVICE_URI")) == NULL)
- {
- /*
- * Build a CUPS_GET_DEVICES request, which requires the following
- * attributes:
- *
- * attributes-charset
- * attributes-natural-language
- * printer-uri
- */
+ if (!cgiGetVariable("CURRENT_MAKE"))
+ cgiSetVariable("CURRENT_MAKE", make);
- request = ippNewRequest(CUPS_GET_DEVICES);
+ if (!cgiGetVariable("CURRENT_MAKE_AND_MODEL"))
+ cgiSetVariable("CURRENT_MAKE_AND_MODEL", uriptr);
- ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
- NULL, "ipp://localhost/printers/");
+ if (!modify)
+ {
+ char template[128], /* Template name */
+ *tptr; /* Pointer into template name */
+
+ cgiSetVariable("PRINTER_INFO", uriptr);
+
+ for (tptr = template;
+ tptr < (template + sizeof(template) - 1) && *uriptr;
+ uriptr ++)
+ if (isalnum(*uriptr & 255) || *uriptr == '_' || *uriptr == '-' ||
+ *uriptr == '.')
+ *tptr++ = *uriptr;
+ else if ((*uriptr == ' ' || *uriptr == '/') && tptr > template &&
+ tptr[-1] != '_')
+ *tptr++ = '_';
+ else if (*uriptr == '?' || *uriptr == '(')
+ break;
- /*
- * Do the request and get back a response...
- */
+ *tptr = '\0';
- if ((response = cupsDoRequest(http, request, "/")) != NULL)
- {
- cgiSetIPPVars(response, NULL, NULL, NULL, 0);
- ippDelete(response);
+ cgiSetVariable("TEMPLATE_NAME", template);
+ }
}
+ }
+ if (!var)
+ {
/*
- * Let the user choose...
+ * Look for devices so the user can pick something...
*/
if ((attr = ippFindAttribute(oldinfo, "device-uri", IPP_TAG_URI)) != NULL)
cgiSetVariable("CURRENT_DEVICE_SCHEME", uri);
}
- cgiStartHTML(title);
- cgiCopyTemplateLang("choose-device.tmpl");
- cgiEndHTML();
+ /*
+ * Scan for devices for up to 30 seconds...
+ */
+
+ fputs("DEBUG: Getting list of devices...\n", stderr);
+
+ current_device = 0;
+ if (cupsGetDevices(http, 5, CUPS_INCLUDE_ALL, CUPS_EXCLUDE_NONE,
+ (cups_device_cb_t)choose_device_cb,
+ (void *)title) == IPP_OK)
+ {
+ fputs("DEBUG: Got device list!\n", stderr);
+
+ if (cgiSupportsMultipart())
+ cgiStartMultipart();
+
+ cgiSetVariable("CUPS_GET_DEVICES_DONE", "1");
+ cgiStartHTML(title);
+ cgiCopyTemplateLang("choose-device.tmpl");
+ cgiEndHTML();
+
+ if (cgiSupportsMultipart())
+ cgiEndMultipart();
+ }
+ else
+ {
+ fprintf(stderr,
+ "ERROR: CUPS-Get-Devices request failed with status %x: %s\n",
+ cupsLastError(), cupsLastErrorString());
+ if (cupsLastError() == IPP_NOT_AUTHORIZED)
+ {
+ puts("Status: 401\n");
+ exit(0);
+ }
+ else
+ {
+ cgiStartHTML(title);
+ cgiShowIPPError(modify ? _("Unable to modify printer") :
+ _("Unable to add printer"));
+ cgiEndHTML();
+ return;
+ }
+ }
}
- else if (strchr(var, '/') == NULL)
+ else if (!strchr(var, '/') ||
+ (!strncmp(var, "lpd://", 6) && !strchr(var + 6, '/')))
{
if ((attr = ippFindAttribute(oldinfo, "device-uri", IPP_TAG_URI)) != NULL)
{
*/
if (strncmp(attr->values[0].string.text, var, strlen(var)) == 0)
- cgiSetVariable("DEVICE_URI", attr->values[0].string.text);
+ cgiSetVariable("CURRENT_DEVICE_URI", attr->values[0].string.text);
}
/*
cgiCopyTemplateLang("choose-serial.tmpl");
cgiEndHTML();
}
- else if (!file && (var = cgiGetVariable("PPD_NAME")) == NULL)
+ else if (!name || !cgiGetVariable("PRINTER_LOCATION"))
{
+ cgiStartHTML(title);
+
if (modify)
+ {
+ /*
+ * Update the location and description of an existing printer...
+ */
+
+ if (oldinfo)
+ {
+ if ((attr = ippFindAttribute(oldinfo, "printer-info",
+ IPP_TAG_TEXT)) != NULL)
+ cgiSetVariable("PRINTER_INFO", attr->values[0].string.text);
+
+ if ((attr = ippFindAttribute(oldinfo, "printer-location",
+ IPP_TAG_TEXT)) != NULL)
+ cgiSetVariable("PRINTER_LOCATION", attr->values[0].string.text);
+
+ if ((attr = ippFindAttribute(oldinfo, "printer-is-shared",
+ IPP_TAG_BOOLEAN)) != NULL)
+ cgiSetVariable("PRINTER_IS_SHARED",
+ attr->values[0].boolean ? "1" : "0");
+ }
+
+ cgiCopyTemplateLang("modify-printer.tmpl");
+ }
+ else
+ {
+ /*
+ * Get the name, location, and description for a new printer...
+ */
+
+#ifdef __APPLE__
+ if (!strncmp(var, "usb:", 4))
+ cgiSetVariable("printer_is_shared", "1");
+ else
+#endif /* __APPLE__ */
+ cgiSetVariable("printer_is_shared", "0");
+
+ cgiCopyTemplateLang("add-printer.tmpl");
+ }
+
+ cgiEndHTML();
+
+ if (oldinfo)
+ ippDelete(oldinfo);
+
+ return;
+ }
+ else if (!file &&
+ (!cgiGetVariable("PPD_NAME") || cgiGetVariable("SELECT_MAKE")))
+ {
+ int ipp_everywhere = !strncmp(var, "ipp://", 6) || !strncmp(var, "ipps://", 7) || (!strncmp(var, "dnssd://", 8) && (strstr(var, "_ipp._tcp") || strstr(var, "_ipps._tcp")));
+
+ if (modify && !cgiGetVariable("SELECT_MAKE"))
{
/*
* Get the PPD file...
char filename[1024]; /* PPD filename */
ppd_file_t *ppd; /* PPD information */
char buffer[1024]; /* Buffer */
- int bytes; /* Number of bytes */
+ ssize_t bytes; /* Number of bytes */
http_status_t get_status; /* Status of GET */
+ /* TODO: Use cupsGetFile() API... */
snprintf(uri, sizeof(uri), "/printers/%s.ppd", name);
if (httpGet(http, uri))
if (get_status != HTTP_OK)
{
+ httpFlush(http);
+
fprintf(stderr, "ERROR: Unable to get PPD file %s: %d - %s\n",
uri, get_status, httpStatus(get_status));
}
else if ((fd = cupsTempFd(filename, sizeof(filename))) >= 0)
{
- while ((bytes = httpRead(http, buffer, sizeof(buffer))) > 0)
- write(fd, buffer, bytes);
+ while ((bytes = httpRead2(http, buffer, sizeof(buffer))) > 0)
+ write(fd, buffer, (size_t)bytes);
close(fd);
}
else
{
+ int linenum; /* Line number */
+
fprintf(stderr, "ERROR: Unable to open PPD file %s: %s\n",
- filename, ppdErrorString(ppdLastError(&bytes)));
+ filename, ppdErrorString(ppdLastError(&linenum)));
}
}
else
strerror(errno));
}
}
- else if ((uriptr = strrchr(cgiGetVariable("DEVICE_URI"), '|')) != NULL)
- {
- /*
- * Extract make and make/model from device URI string...
- */
-
- char make[1024], /* Make string */
- *makeptr; /* Pointer into make */
-
-
- *uriptr++ = '\0';
-
- strlcpy(make, uriptr, sizeof(make));
-
- if ((makeptr = strchr(make, ' ')) != NULL)
- *makeptr = '\0';
- else if ((makeptr = strchr(make, '-')) != NULL)
- *makeptr = '\0';
- else if (!strncasecmp(make, "laserjet", 8) ||
- !strncasecmp(make, "deskjet", 7) ||
- !strncasecmp(make, "designjet", 9))
- strcpy(make, "HP");
- else if (!strncasecmp(make, "phaser", 6))
- strcpy(make, "Xerox");
- else if (!strncasecmp(make, "stylus", 6))
- strcpy(make, "Epson");
- else
- strcpy(make, "Generic");
-
- cgiSetVariable("CURRENT_MAKE", make);
- cgiSetVariable("PPD_MAKE", make);
- cgiSetVariable("CURRENT_MAKE_AND_MODEL", uriptr);
- }
/*
* Build a CUPS_GET_PPDS request, which requires the following
ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
NULL, "ipp://localhost/printers/");
- if ((var = cgiGetVariable("PPD_MAKE")) != NULL)
+ if ((var = cgiGetVariable("PPD_MAKE")) == NULL)
+ var = cgiGetVariable("CURRENT_MAKE");
+ if (var && !cgiGetVariable("SELECT_MAKE"))
+ {
+ const char *make_model; /* Make and model */
+
+
ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_TEXT,
"ppd-make", NULL, var);
+
+ if ((make_model = cgiGetVariable("CURRENT_MAKE_AND_MODEL")) != NULL)
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_TEXT,
+ "ppd-make-and-model", NULL, make_model);
+ }
else
ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
"requested-attributes", NULL, "ppd-make");
* Got the list of PPDs, see if the user has selected a make...
*/
- cgiSetIPPVars(response, NULL, NULL, NULL, 0);
-
- if (var == NULL)
+ if (cgiSetIPPVars(response, NULL, NULL, NULL, 0) == 0 && !modify)
{
/*
- * Let the user choose a make...
+ * No PPD files with this make, try again with all makes...
*/
- for (element = 0, attr = response->attrs, last = NULL;
- attr != NULL;
- attr = attr->next)
- if (attr->name && strcmp(attr->name, "ppd-make") == 0)
- if (last == NULL ||
- strcasecmp(last->values[0].string.text,
- attr->values[0].string.text) != 0)
- {
- cgiSetArray("PPD_MAKE", element, attr->values[0].string.text);
- element ++;
- last = attr;
- }
+ ippDelete(response);
+
+ request = ippNewRequest(CUPS_GET_PPDS);
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
+ NULL, "ipp://localhost/printers/");
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
+ "requested-attributes", NULL, "ppd-make");
+ if ((response = cupsDoRequest(http, request, "/")) != NULL)
+ cgiSetIPPVars(response, NULL, NULL, NULL, 0);
+
+ cgiStartHTML(title);
+ cgiCopyTemplateLang("choose-make.tmpl");
+ cgiEndHTML();
+ }
+ else if (!var || cgiGetVariable("SELECT_MAKE"))
+ {
cgiStartHTML(title);
cgiCopyTemplateLang("choose-make.tmpl");
cgiEndHTML();
* 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);
+ if (!cgiGetVariable("PPD_MAKE"))
+ cgiSetVariable("PPD_MAKE", cgiGetVariable("CURRENT_MAKE"));
+ if (ipp_everywhere)
+ cgiSetVariable("SHOW_IPP_EVERYWHERE", "1");
cgiCopyTemplateLang("choose-model.tmpl");
cgiEndHTML();
}
-
ippDelete(response);
}
else
{
cgiStartHTML(title);
- cgiShowIPPError(_("Unable to get list of printer drivers:"));
+ cgiShowIPPError(_("Unable to get list of printer drivers"));
cgiCopyTemplateLang("error.tmpl");
cgiEndHTML();
}
* ppd-name
* device-uri
* printer-is-accepting-jobs
+ * printer-is-shared
* printer-state
*/
request = ippNewRequest(CUPS_ADD_PRINTER);
- httpAssembleURIf(uri, sizeof(uri), "ipp", NULL, "localhost", 0,
- "/printers/%s", cgiGetVariable("PRINTER_NAME"));
+ httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
+ "localhost", 0, "/printers/%s",
+ cgiGetVariable("PRINTER_NAME"));
ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
NULL, uri);
+ if (!file)
+ {
+ var = cgiGetVariable("PPD_NAME");
+ if (!strcmp(var, "everywhere"))
+ get_printer_ppd(cgiGetVariable("DEVICE_URI"), evefile, sizeof(evefile));
+ else if (strcmp(var, "__no_change__"))
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "ppd-name",
+ NULL, var);
+ }
+
ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-location",
NULL, cgiGetVariable("PRINTER_LOCATION"));
ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-info",
NULL, cgiGetVariable("PRINTER_INFO"));
- if (!file)
- ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_NAME, "ppd-name",
- NULL, cgiGetVariable("PPD_NAME"));
-
strlcpy(uri, cgiGetVariable("DEVICE_URI"), sizeof(uri));
/*
if ((uriptr = strchr(uri, '?')) == NULL)
uriptr = uri + strlen(uri);
- snprintf(uriptr, sizeof(uri) - (uriptr - uri),
+ snprintf(uriptr, sizeof(uri) - (size_t)(uriptr - uri),
"?baud=%s+bits=%s+parity=%s+flow=%s",
cgiGetVariable("BAUDRATE"), cgiGetVariable("BITS"),
cgiGetVariable("PARITY"), cgiGetVariable("FLOW"));
ippAddBoolean(request, IPP_TAG_PRINTER, "printer-is-accepting-jobs", 1);
+ var = cgiGetVariable("printer_is_shared");
+ ippAddBoolean(request, IPP_TAG_PRINTER, "printer-is-shared",
+ var && (!strcmp(var, "1") || !strcmp(var, "on")));
+
ippAddInteger(request, IPP_TAG_PRINTER, IPP_TAG_ENUM, "printer-state",
IPP_PRINTER_IDLE);
if (file)
ippDelete(cupsDoFileRequest(http, request, "/admin/", file->tempfile));
+ else if (evefile[0])
+ {
+ ippDelete(cupsDoFileRequest(http, request, "/admin/", evefile));
+ unlink(evefile);
+ }
else
ippDelete(cupsDoRequest(http, request, "/admin/"));
- if (cupsLastError() > IPP_OK_CONFLICT)
+ if (cupsLastError() == IPP_NOT_AUTHORIZED)
+ {
+ puts("Status: 401\n");
+ exit(0);
+ }
+ else if (cupsLastError() > IPP_OK_CONFLICT)
{
cgiStartHTML(title);
- cgiShowIPPError(modify ? _("Unable to modify printer:") :
- _("Unable to add printer:"));
+ cgiShowIPPError(modify ? _("Unable to modify printer") :
+ _("Unable to add printer"));
}
- else
+ else if (modify)
{
/*
- * Redirect successful updates back to the printer or set-options pages...
+ * Redirect successful updates back to the printer page...
*/
char refresh[1024]; /* Refresh URL */
cgiFormEncode(uri, name, sizeof(uri));
- if (modify)
- snprintf(refresh, sizeof(refresh),
- "5;/admin/?OP=redirect&URL=/printers/%s", uri);
- else
- snprintf(refresh, sizeof(refresh),
- "5;/admin/?OP=set-printer-options&PRINTER_NAME=%s", uri);
+ snprintf(refresh, sizeof(refresh),
+ "5;/admin/?OP=redirect&URL=/printers/%s", uri);
cgiSetVariable("refresh_page", refresh);
cgiStartHTML(title);
- if (modify)
- cgiCopyTemplateLang("printer-modified.tmpl");
- else
- cgiCopyTemplateLang("printer-added.tmpl");
+ cgiCopyTemplateLang("printer-modified.tmpl");
+ }
+ else
+ {
+ /*
+ * Set the printer options...
+ */
+
+ cgiSetVariable("OP", "set-printer-options");
+ do_set_options(http, 0);
+ return;
}
cgiEndHTML();
/*
- * 'do_config_printer()' - Configure the default options for a printer.
+ * 'do_config_server()' - Configure server settings.
*/
static void
-do_config_printer(http_t *http) /* I - HTTP connection */
+do_config_server(http_t *http) /* I - HTTP connection */
{
- int i, j, k, m; /* Looping vars */
- int have_options; /* Have options? */
- ipp_t *request, /* IPP request */
- *response; /* IPP response */
- ipp_attribute_t *attr; /* IPP attribute */
- char uri[HTTP_MAX_URI]; /* Job URI */
- const char *var; /* Variable value */
- const char *printer; /* Printer printer name */
- const char *filename; /* PPD filename */
- char tempfile[1024]; /* Temporary filename */
- cups_file_t *in, /* Input file */
- *out; /* Output file */
- char line[1024]; /* Line from PPD file */
- char keyword[1024], /* Keyword from Default line */
- *keyptr; /* Pointer into keyword... */
- ppd_file_t *ppd; /* PPD file */
- ppd_group_t *group; /* Option group */
- ppd_option_t *option; /* Option */
- ppd_attr_t *protocol; /* cupsProtocol attribute */
- const char *title; /* Page title */
-
-
- title = cgiText(_("Set Printer Options"));
+ if (cgiGetVariable("CHANGESETTINGS"))
+ {
+ /*
+ * Save basic setting changes...
+ */
- /*
- * Get the printer name...
- */
+ int num_settings; /* Number of server settings */
+ cups_option_t *settings; /* Server settings */
+ int advanced, /* Advanced settings shown? */
+ changed; /* Have settings changed? */
+ const char *debug_logging, /* DEBUG_LOGGING value */
+ *preserve_jobs = NULL,
+ /* PRESERVE_JOBS value */
+ *remote_admin, /* REMOTE_ADMIN value */
+ *remote_any, /* REMOTE_ANY value */
+ *share_printers,/* SHARE_PRINTERS value */
+ *user_cancel_any,
+ /* USER_CANCEL_ANY value */
+ *browse_web_if = NULL,
+ /* BrowseWebIF value */
+ *preserve_job_history = NULL,
+ /* PreserveJobHistory value */
+ *preserve_job_files = NULL,
+ /* PreserveJobFiles value */
+ *max_clients = NULL,
+ /* MaxClients value */
+ *max_jobs = NULL,
+ /* MaxJobs value */
+ *max_log_size = NULL;
+ /* MaxLogSize value */
+ const char *current_browse_web_if,
+ /* BrowseWebIF value */
+ *current_preserve_job_history,
+ /* PreserveJobHistory value */
+ *current_preserve_job_files,
+ /* PreserveJobFiles value */
+ *current_max_clients,
+ /* MaxClients value */
+ *current_max_jobs,
+ /* MaxJobs value */
+ *current_max_log_size;
+ /* MaxLogSize value */
+#ifdef HAVE_GSSAPI
+ char default_auth_type[255];
+ /* DefaultAuthType value */
+ const char *val; /* Setting value */
+#endif /* HAVE_GSSAPI */
- if ((printer = cgiGetVariable("PRINTER_NAME")) != NULL)
- httpAssembleURIf(uri, sizeof(uri), "ipp", NULL, "localhost", 0,
- "/printers/%s", printer);
- else
- {
- cgiSetVariable("ERROR", cgiText(_("Missing form variable!")));
- cgiStartHTML(title);
- cgiCopyTemplateLang("error.tmpl");
- cgiEndHTML();
- return;
- }
- /*
- * Get the PPD file...
- */
+ /*
+ * Get the checkbox values from the form...
+ */
- if ((filename = cupsGetPPD(printer)) == NULL)
- {
- cgiStartHTML(title);
- cgiShowIPPError(_("Unable to get PPD file!"));
- cgiEndHTML();
- return;
- }
+ debug_logging = cgiGetVariable("DEBUG_LOGGING") ? "1" : "0";
+ remote_admin = cgiGetVariable("REMOTE_ADMIN") ? "1" : "0";
+ remote_any = cgiGetVariable("REMOTE_ANY") ? "1" : "0";
+ share_printers = cgiGetVariable("SHARE_PRINTERS") ? "1" : "0";
+ user_cancel_any = cgiGetVariable("USER_CANCEL_ANY") ? "1" : "0";
- if ((ppd = ppdOpenFile(filename)) == NULL)
- {
- cgiSetVariable("ERROR", ppdErrorString(ppdLastError(&i)));
- cgiSetVariable("MESSAGE", cgiText(_("Unable to open PPD file:")));
- cgiStartHTML(title);
- cgiCopyTemplateLang("error.tmpl");
- cgiEndHTML();
- return;
- }
+ advanced = cgiGetVariable("ADVANCEDSETTINGS") != NULL;
+ if (advanced)
+ {
+ /*
+ * Get advanced settings...
+ */
- if (cgiGetVariable("job_sheets_start") != NULL ||
- cgiGetVariable("job_sheets_end") != NULL)
- have_options = 1;
- else
- have_options = 0;
+ browse_web_if = cgiGetVariable("BROWSE_WEB_IF") ? "Yes" : "No";
+ max_clients = cgiGetVariable("MAX_CLIENTS");
+ max_log_size = cgiGetVariable("MAX_LOG_SIZE");
+ preserve_jobs = cgiGetVariable("PRESERVE_JOBS");
- ppdMarkDefaults(ppd);
+ if (preserve_jobs)
+ {
+ max_jobs = cgiGetVariable("MAX_JOBS");
+ preserve_job_history = cgiGetVariable("PRESERVE_JOB_HISTORY");
+ preserve_job_files = cgiGetVariable("PRESERVE_JOB_FILES");
- DEBUG_printf(("<P>ppd->num_groups = %d\n"
- "<UL>\n", ppd->num_groups));
+ if (!max_jobs || atoi(max_jobs) < 0)
+ max_jobs = "500";
- for (i = ppd->num_groups, group = ppd->groups; i > 0; i --, group ++)
- {
- DEBUG_printf(("<LI>%s<UL>\n", group->text));
+ if (!preserve_job_history)
+ preserve_job_history = "On";
- for (j = group->num_options, option = group->options; j > 0; j --, option ++)
- if ((var = cgiGetVariable(option->keyword)) != NULL)
- {
- DEBUG_printf(("<LI>%s = \"%s\"</LI>\n", option->keyword, var));
- have_options = 1;
- ppdMarkOption(ppd, option->keyword, var);
+ if (!preserve_job_files)
+ preserve_job_files = "1d";
}
-#ifdef DEBUG
else
- printf("<LI>%s not defined!</LI>\n", option->keyword);
-#endif /* DEBUG */
+ {
+ max_jobs = "0";
+ preserve_job_history = "No";
+ preserve_job_files = "No";
+ }
- DEBUG_puts("</UL></LI>");
- }
+ if (!max_clients || atoi(max_clients) <= 0)
+ max_clients = "100";
- DEBUG_printf(("</UL>\n"
- "<P>ppdConflicts(ppd) = %d\n", ppdConflicts(ppd)));
+ if (!max_log_size || atoi(max_log_size) <= 0.0)
+ max_log_size = "1m";
+ }
- if (!have_options || ppdConflicts(ppd))
- {
/*
- * Show the options to the user...
+ * Get the current server settings...
*/
- ppdLocalize(ppd);
-
- cgiStartHTML("Set Printer Options");
- cgiCopyTemplateLang("set-printer-options-header.tmpl");
-
- if (ppdConflicts(ppd))
+ if (!cupsAdminGetServerSettings(http, &num_settings, &settings))
{
- for (i = ppd->num_groups, k = 0, group = ppd->groups; i > 0; i --, group ++)
- for (j = group->num_options, option = group->options; j > 0; j --, option ++)
- if (option->conflicted)
- {
- cgiSetArray("ckeyword", k, option->keyword);
- cgiSetArray("ckeytext", k, option->text);
- k ++;
- }
-
- cgiCopyTemplateLang("option-conflict.tmpl");
+ cgiStartHTML(cgiText(_("Change Settings")));
+ cgiSetVariable("MESSAGE",
+ cgiText(_("Unable to change server settings")));
+ cgiSetVariable("ERROR", cupsLastErrorString());
+ cgiCopyTemplateLang("error.tmpl");
+ cgiEndHTML();
+ return;
}
- for (i = ppd->num_groups, group = ppd->groups;
- i > 0;
- i --, group ++)
- {
- if (!strcmp(group->name, "InstallableOptions"))
- cgiSetVariable("GROUP", cgiText(_("Options Installed")));
- else
- cgiSetVariable("GROUP", group->text);
-
- cgiCopyTemplateLang("option-header.tmpl");
-
- for (j = group->num_options, option = group->options;
- j > 0;
- j --, option ++)
- {
- if (!strcmp(option->keyword, "PageRegion"))
- continue;
-
- cgiSetVariable("KEYWORD", option->keyword);
- cgiSetVariable("KEYTEXT", option->text);
-
- if (option->conflicted)
- cgiSetVariable("CONFLICTED", "1");
- else
- cgiSetVariable("CONFLICTED", "0");
-
- cgiSetSize("CHOICES", 0);
- cgiSetSize("TEXT", 0);
- for (k = 0, m = 0; k < option->num_choices; k ++)
- {
- /*
- * Hide custom option values...
- */
+#ifdef HAVE_GSSAPI
+ /*
+ * Get authentication settings...
+ */
- if (!strcmp(option->choices[k].choice, "Custom"))
- continue;
+ if (cgiGetVariable("KERBEROS"))
+ strlcpy(default_auth_type, "Negotiate", sizeof(default_auth_type));
+ else
+ {
+ val = cupsGetOption("DefaultAuthType", num_settings, settings);
- cgiSetArray("CHOICES", m, option->choices[k].choice);
- cgiSetArray("TEXT", m, option->choices[k].text);
+ if (!val || !_cups_strcasecmp(val, "Negotiate"))
+ strlcpy(default_auth_type, "Basic", sizeof(default_auth_type));
+ else
+ strlcpy(default_auth_type, val, sizeof(default_auth_type));
+ }
- m ++;
+ fprintf(stderr, "DEBUG: DefaultAuthType %s\n", default_auth_type);
+#endif /* HAVE_GSSAPI */
- if (option->choices[k].marked)
- cgiSetVariable("DEFCHOICE", option->choices[k].choice);
- }
+ if ((current_browse_web_if = cupsGetOption("BrowseWebIF", num_settings,
+ settings)) == NULL)
+ current_browse_web_if = "No";
- switch (option->ui)
- {
- case PPD_UI_BOOLEAN :
- cgiCopyTemplateLang("option-boolean.tmpl");
- break;
- case PPD_UI_PICKONE :
- cgiCopyTemplateLang("option-pickone.tmpl");
- break;
- case PPD_UI_PICKMANY :
- cgiCopyTemplateLang("option-pickmany.tmpl");
- break;
- }
- }
+ if ((current_preserve_job_history = cupsGetOption("PreserveJobHistory",
+ num_settings,
+ settings)) == NULL)
+ current_preserve_job_history = "Yes";
- cgiCopyTemplateLang("option-trailer.tmpl");
- }
+ if ((current_preserve_job_files = cupsGetOption("PreserveJobFiles",
+ num_settings,
+ settings)) == NULL)
+ current_preserve_job_files = "1d";
- /*
- * Build an IPP_GET_PRINTER_ATTRIBUTES request, which requires the
- * following attributes:
- *
- * attributes-charset
- * attributes-natural-language
- * printer-uri
- */
+ if ((current_max_clients = cupsGetOption("MaxClients", num_settings,
+ settings)) == NULL)
+ current_max_clients = "100";
- request = ippNewRequest(IPP_GET_PRINTER_ATTRIBUTES);
+ if ((current_max_jobs = cupsGetOption("MaxJobs", num_settings,
+ settings)) == NULL)
+ current_max_jobs = "500";
- httpAssembleURIf(uri, sizeof(uri), "ipp", NULL, "localhost", 0,
- "/printers/%s", printer);
- ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
- NULL, uri);
+ if ((current_max_log_size = cupsGetOption("MaxLogSize", num_settings,
+ settings)) == NULL)
+ current_max_log_size = "1m";
/*
- * Do the request and get back a response...
+ * See if the settings have changed...
*/
- if ((response = cupsDoRequest(http, request, "/")) != NULL)
+ changed = strcmp(debug_logging, cupsGetOption(CUPS_SERVER_DEBUG_LOGGING,
+ num_settings, settings)) ||
+ strcmp(remote_admin, cupsGetOption(CUPS_SERVER_REMOTE_ADMIN,
+ num_settings, settings)) ||
+ strcmp(remote_any, cupsGetOption(CUPS_SERVER_REMOTE_ANY,
+ num_settings, settings)) ||
+ strcmp(share_printers, cupsGetOption(CUPS_SERVER_SHARE_PRINTERS,
+ num_settings, settings)) ||
+#ifdef HAVE_GSSAPI
+ !cupsGetOption("DefaultAuthType", num_settings, settings) ||
+ strcmp(default_auth_type, cupsGetOption("DefaultAuthType",
+ num_settings, settings)) ||
+#endif /* HAVE_GSSAPI */
+ strcmp(user_cancel_any, cupsGetOption(CUPS_SERVER_USER_CANCEL_ANY,
+ num_settings, settings));
+
+ if (advanced && !changed)
+ changed = _cups_strcasecmp(browse_web_if, current_browse_web_if) ||
+ _cups_strcasecmp(preserve_job_history, current_preserve_job_history) ||
+ _cups_strcasecmp(preserve_job_files, current_preserve_job_files) ||
+ _cups_strcasecmp(max_clients, current_max_clients) ||
+ _cups_strcasecmp(max_jobs, current_max_jobs) ||
+ _cups_strcasecmp(max_log_size, current_max_log_size);
+
+ if (changed)
{
- if ((attr = ippFindAttribute(response, "job-sheets-supported",
- IPP_TAG_ZERO)) != NULL)
+ /*
+ * Settings *have* changed, so save the changes...
+ */
+
+ cupsFreeOptions(num_settings, settings);
+
+ num_settings = 0;
+ num_settings = cupsAddOption(CUPS_SERVER_DEBUG_LOGGING,
+ debug_logging, num_settings, &settings);
+ num_settings = cupsAddOption(CUPS_SERVER_REMOTE_ADMIN,
+ remote_admin, num_settings, &settings);
+ num_settings = cupsAddOption(CUPS_SERVER_REMOTE_ANY,
+ remote_any, num_settings, &settings);
+ num_settings = cupsAddOption(CUPS_SERVER_SHARE_PRINTERS,
+ share_printers, num_settings, &settings);
+ num_settings = cupsAddOption(CUPS_SERVER_USER_CANCEL_ANY,
+ user_cancel_any, num_settings, &settings);
+#ifdef HAVE_GSSAPI
+ num_settings = cupsAddOption("DefaultAuthType", default_auth_type,
+ num_settings, &settings);
+#endif /* HAVE_GSSAPI */
+
+ if (advanced)
{
/*
- * Add the job sheets options...
+ * Add advanced settings...
*/
- cgiSetVariable("GROUP", cgiText(_("Banners")));
- cgiCopyTemplateLang("option-header.tmpl");
+ if (_cups_strcasecmp(browse_web_if, current_browse_web_if))
+ num_settings = cupsAddOption("BrowseWebIF", browse_web_if,
+ num_settings, &settings);
+ if (_cups_strcasecmp(preserve_job_history, current_preserve_job_history))
+ num_settings = cupsAddOption("PreserveJobHistory",
+ preserve_job_history, num_settings,
+ &settings);
+ if (_cups_strcasecmp(preserve_job_files, current_preserve_job_files))
+ num_settings = cupsAddOption("PreserveJobFiles", preserve_job_files,
+ num_settings, &settings);
+ if (_cups_strcasecmp(max_clients, current_max_clients))
+ num_settings = cupsAddOption("MaxClients", max_clients, num_settings,
+ &settings);
+ if (_cups_strcasecmp(max_jobs, current_max_jobs))
+ num_settings = cupsAddOption("MaxJobs", max_jobs, num_settings,
+ &settings);
+ if (_cups_strcasecmp(max_log_size, current_max_log_size))
+ num_settings = cupsAddOption("MaxLogSize", max_log_size, num_settings,
+ &settings);
+ }
- cgiSetSize("CHOICES", attr->num_values);
- cgiSetSize("TEXT", attr->num_values);
- for (k = 0; k < attr->num_values; k ++)
+ if (!cupsAdminSetServerSettings(http, num_settings, settings))
+ {
+ if (cupsLastError() == IPP_NOT_AUTHORIZED)
{
- cgiSetArray("CHOICES", k, attr->values[k].string.text);
- cgiSetArray("TEXT", k, attr->values[k].string.text);
+ puts("Status: 401\n");
+ exit(0);
}
- attr = ippFindAttribute(response, "job-sheets-default", IPP_TAG_ZERO);
-
- cgiSetVariable("KEYWORD", "job_sheets_start");
- cgiSetVariable("KEYTEXT", cgiText(_("Starting Banner")));
- cgiSetVariable("DEFCHOICE", attr == NULL ?
- "" : attr->values[0].string.text);
-
- cgiCopyTemplateLang("option-pickone.tmpl");
-
- cgiSetVariable("KEYWORD", "job_sheets_end");
- cgiSetVariable("KEYTEXT", cgiText(_("Ending Banner")));
- cgiSetVariable("DEFCHOICE", attr == NULL && attr->num_values > 1 ?
- "" : attr->values[1].string.text);
-
- cgiCopyTemplateLang("option-pickone.tmpl");
-
- cgiCopyTemplateLang("option-trailer.tmpl");
+ cgiStartHTML(cgiText(_("Change Settings")));
+ cgiSetVariable("MESSAGE",
+ cgiText(_("Unable to change server settings")));
+ cgiSetVariable("ERROR", cupsLastErrorString());
+ cgiCopyTemplateLang("error.tmpl");
}
-
- if (ippFindAttribute(response, "printer-error-policy-supported",
- IPP_TAG_ZERO) ||
- ippFindAttribute(response, "printer-op-policy-supported",
- IPP_TAG_ZERO))
+ else
{
- /*
- * Add the error and operation policy options...
- */
+ if (advanced)
+ cgiSetVariable("refresh_page", "5;URL=/admin/?OP=redirect&"
+ "URL=/admin/?ADVANCEDSETTINGS=YES");
+ else
+ cgiSetVariable("refresh_page", "5;URL=/admin/?OP=redirect");
+ cgiStartHTML(cgiText(_("Change Settings")));
+ cgiCopyTemplateLang("restart.tmpl");
+ }
+ }
+ else
+ {
+ /*
+ * No changes...
+ */
- cgiSetVariable("GROUP", cgiText(_("Policies")));
- cgiCopyTemplateLang("option-header.tmpl");
+ cgiSetVariable("refresh_page", "5;URL=/admin/?OP=redirect");
+ cgiStartHTML(cgiText(_("Change Settings")));
+ cgiCopyTemplateLang("norestart.tmpl");
+ }
- /*
- * Error policy...
- */
+ cupsFreeOptions(num_settings, settings);
- attr = ippFindAttribute(response, "printer-error-policy-supported",
- IPP_TAG_ZERO);
+ cgiEndHTML();
+ }
+ else if (cgiGetVariable("SAVECHANGES") && cgiGetVariable("CUPSDCONF"))
+ {
+ /*
+ * Save hand-edited config file...
+ */
- if (attr)
- {
- cgiSetSize("CHOICES", attr->num_values);
- cgiSetSize("TEXT", attr->num_values);
- for (k = 0; k < attr->num_values; k ++)
- {
- cgiSetArray("CHOICES", k, attr->values[k].string.text);
- cgiSetArray("TEXT", k, attr->values[k].string.text);
- }
+ http_status_t status; /* PUT status */
+ char tempfile[1024]; /* Temporary new cupsd.conf */
+ int tempfd; /* Temporary file descriptor */
+ cups_file_t *temp; /* Temporary file */
+ const char *start, /* Start of line */
+ *end; /* End of line */
- attr = ippFindAttribute(response, "printer-error-policy",
- IPP_TAG_ZERO);
- cgiSetVariable("KEYWORD", "printer_error_policy");
- cgiSetVariable("KEYTEXT", cgiText(_("Error Policy")));
- cgiSetVariable("DEFCHOICE", attr == NULL ?
- "" : attr->values[0].string.text);
- }
+ /*
+ * Create a temporary file for the new cupsd.conf file...
+ */
- cgiCopyTemplateLang("option-pickone.tmpl");
+ if ((tempfd = cupsTempFd(tempfile, sizeof(tempfile))) < 0)
+ {
+ cgiStartHTML(cgiText(_("Edit Configuration File")));
+ cgiSetVariable("MESSAGE", cgiText(_("Unable to create temporary file")));
+ cgiSetVariable("ERROR", strerror(errno));
+ cgiCopyTemplateLang("error.tmpl");
+ cgiEndHTML();
- /*
- * Operation policy...
- */
-
- attr = ippFindAttribute(response, "printer-op-policy-supported",
- IPP_TAG_ZERO);
-
- if (attr)
- {
- cgiSetSize("CHOICES", attr->num_values);
- cgiSetSize("TEXT", attr->num_values);
- for (k = 0; k < attr->num_values; k ++)
- {
- cgiSetArray("CHOICES", k, attr->values[k].string.text);
- cgiSetArray("TEXT", k, attr->values[k].string.text);
- }
-
- attr = ippFindAttribute(response, "printer-op-policy", IPP_TAG_ZERO);
-
- cgiSetVariable("KEYWORD", "printer_op_policy");
- cgiSetVariable("KEYTEXT", cgiText(_("Operation Policy")));
- cgiSetVariable("DEFCHOICE", attr == NULL ?
- "" : attr->values[0].string.text);
-
- cgiCopyTemplateLang("option-pickone.tmpl");
- }
-
- cgiCopyTemplateLang("option-trailer.tmpl");
- }
-
- ippDelete(response);
- }
-
- /*
- * Binary protocol support...
- */
-
- if (ppd->protocols && strstr(ppd->protocols, "BCP"))
- {
- protocol = ppdFindAttr(ppd, "cupsProtocol", NULL);
-
- cgiSetVariable("GROUP", cgiText(_("PS Binary Protocol")));
- cgiCopyTemplateLang("option-header.tmpl");
-
- cgiSetSize("CHOICES", 2);
- cgiSetSize("TEXT", 2);
- cgiSetArray("CHOICES", 0, "None");
- cgiSetArray("TEXT", 0, cgiText(_("None")));
-
- if (strstr(ppd->protocols, "TBCP"))
- {
- cgiSetArray("CHOICES", 1, "TBCP");
- cgiSetArray("TEXT", 1, "TBCP");
- }
- else
- {
- cgiSetArray("CHOICES", 1, "BCP");
- cgiSetArray("TEXT", 1, "BCP");
- }
-
- cgiSetVariable("KEYWORD", "protocol");
- cgiSetVariable("KEYTEXT", cgiText(_("PS Binary Protocol")));
- cgiSetVariable("DEFCHOICE", protocol ? protocol->value : "None");
-
- cgiCopyTemplateLang("option-pickone.tmpl");
-
- cgiCopyTemplateLang("option-trailer.tmpl");
+ perror(tempfile);
+ return;
}
- cgiCopyTemplateLang("set-printer-options-trailer.tmpl");
- cgiEndHTML();
- }
- else
- {
- /*
- * Set default options...
- */
-
- out = cupsTempFile2(tempfile, sizeof(tempfile));
- in = cupsFileOpen(filename, "r");
-
- if (!in || !out)
+ if ((temp = cupsFileOpenFd(tempfd, "w")) == NULL)
{
+ cgiStartHTML(cgiText(_("Edit Configuration File")));
+ cgiSetVariable("MESSAGE", cgiText(_("Unable to create temporary file")));
cgiSetVariable("ERROR", strerror(errno));
- cgiStartHTML("Set Printer Options");
cgiCopyTemplateLang("error.tmpl");
cgiEndHTML();
- if (in)
- cupsFileClose(in);
-
- if (out)
- {
- cupsFileClose(out);
- unlink(tempfile);
- }
-
- unlink(filename);
+ perror(tempfile);
+ close(tempfd);
+ unlink(tempfile);
return;
}
- while (cupsFileGets(in, line, sizeof(line)))
- {
- if (!strncmp(line, "*cupsProtocol:", 14) && cgiGetVariable("protocol"))
- continue;
- else if (strncmp(line, "*Default", 8))
- cupsFilePrintf(out, "%s\n", line);
- else
- {
- /*
- * Get default option name...
- */
-
- strlcpy(keyword, line + 8, sizeof(keyword));
-
- for (keyptr = keyword; *keyptr; keyptr ++)
- if (*keyptr == ':' || isspace(*keyptr & 255))
- break;
-
- *keyptr = '\0';
-
- if (!strcmp(keyword, "PageRegion"))
- var = cgiGetVariable("PageSize");
- else
- var = cgiGetVariable(keyword);
-
- if (var != NULL)
- cupsFilePrintf(out, "*Default%s: %s\n", keyword, var);
- else
- cupsFilePrintf(out, "%s\n", line);
- }
- }
-
- if ((var = cgiGetVariable("protocol")) != NULL)
- cupsFilePrintf(out, "*cupsProtocol: %s\n", cgiGetVariable("protocol"));
-
- cupsFileClose(in);
- cupsFileClose(out);
-
/*
- * Build a CUPS_ADD_PRINTER request, which requires the following
- * attributes:
- *
- * attributes-charset
- * attributes-natural-language
- * printer-uri
- * job-sheets-default
- * [ppd file]
+ * Copy the cupsd.conf text from the form variable...
*/
- request = ippNewRequest(CUPS_ADD_PRINTER);
-
- httpAssembleURIf(uri, sizeof(uri), "ipp", NULL, "localhost", 0,
- "/printers/%s", cgiGetVariable("PRINTER_NAME"));
- ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
- NULL, uri);
+ start = cgiGetVariable("CUPSDCONF");
+ while (start)
+ {
+ if ((end = strstr(start, "\r\n")) == NULL)
+ if ((end = strstr(start, "\n")) == NULL)
+ end = start + strlen(start);
- attr = ippAddStrings(request, IPP_TAG_PRINTER, IPP_TAG_NAME,
- "job-sheets-default", 2, NULL, NULL);
- attr->values[0].string.text = strdup(cgiGetVariable("job_sheets_start"));
- attr->values[1].string.text = strdup(cgiGetVariable("job_sheets_end"));
+ cupsFileWrite(temp, start, (size_t)(end - start));
+ cupsFilePutChar(temp, '\n');
- if ((var = cgiGetVariable("printer_error_policy")) != NULL)
- attr = ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_NAME,
- "printer-error-policy", NULL, var);
+ if (*end == '\r')
+ start = end + 2;
+ else if (*end == '\n')
+ start = end + 1;
+ else
+ start = NULL;
+ }
- if ((var = cgiGetVariable("printer_op_policy")) != NULL)
- attr = ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_NAME,
- "printer-op-policy", NULL, var);
+ cupsFileClose(temp);
/*
- * Do the request and get back a response...
+ * Upload the configuration file to the server...
*/
- ippDelete(cupsDoFileRequest(http, request, "/admin/", tempfile));
+ status = cupsPutFile(http, "/admin/conf/cupsd.conf", tempfile);
- if (cupsLastError() > IPP_OK_CONFLICT)
+ if (status == HTTP_UNAUTHORIZED)
{
- cgiStartHTML(title);
- cgiShowIPPError(_("Unable to set options:"));
+ puts("Status: 401\n");
+ unlink(tempfile);
+ exit(0);
}
- else
+ else if (status != HTTP_CREATED)
{
- /*
- * Redirect successful updates back to the printer page...
- */
-
- char refresh[1024]; /* Refresh URL */
-
-
- cgiFormEncode(uri, printer, sizeof(uri));
- snprintf(refresh, sizeof(refresh), "5;/admin/?OP=redirect&URL=/printers/%s",
- uri);
- cgiSetVariable("refresh_page", refresh);
+ cgiSetVariable("MESSAGE",
+ cgiText(_("Unable to upload cupsd.conf file")));
+ cgiSetVariable("ERROR", httpStatus(status));
- cgiStartHTML(title);
+ cgiStartHTML(cgiText(_("Edit Configuration File")));
+ cgiCopyTemplateLang("error.tmpl");
+ }
+ else
+ {
+ cgiSetVariable("refresh_page", "5;URL=/admin/");
- cgiCopyTemplateLang("printer-configured.tmpl");
+ cgiStartHTML(cgiText(_("Edit Configuration File")));
+ cgiCopyTemplateLang("restart.tmpl");
}
cgiEndHTML();
unlink(tempfile);
}
-
- unlink(filename);
-}
-
-
-/*
- * 'do_config_server()' - Configure server settings.
- */
-
-static void
-do_config_server(http_t *http) /* I - HTTP connection */
-{
- if (cgiIsPOST() && !cgiGetVariable("CUPSDCONF"))
+ else
{
- /*
- * Save basic setting changes...
- */
-
- http_status_t status; /* PUT status */
+ struct stat info; /* cupsd.conf information */
cups_file_t *cupsd; /* cupsd.conf file */
- char tempfile[1024]; /* Temporary new cupsd.conf */
- int tempfd; /* Temporary file descriptor */
- cups_file_t *temp; /* Temporary file */
- char line[1024], /* Line from cupsd.conf file */
- *value; /* Value on line */
+ char *buffer, /* Buffer for entire file */
+ *bufptr, /* Pointer into buffer */
+ *bufend; /* End of buffer */
+ int ch; /* Character from file */
+ char filename[1024]; /* Filename */
const char *server_root; /* Location of config files */
- int linenum, /* Line number in file */
- in_policy, /* In a policy section? */
- in_cancel_job, /* In a cancel-job section? */
- in_admin_location, /* In the /admin location? */
- in_conf_location, /* In the /admin/conf location? */
- in_root_location; /* In the / location? */
- int remote_printers, /* Show remote printers */
- share_printers, /* Share local printers */
- remote_admin, /* Remote administration allowed? */
- user_cancel_any, /* Cancel-job policy set? */
- debug_logging; /* LogLevel debug set? */
- int wrote_port_listen, /* Wrote the port/listen lines? */
- wrote_browsing, /* Wrote the browsing lines? */
- wrote_policy, /* Wrote the policy? */
- wrote_loglevel, /* Wrote the LogLevel line? */
- wrote_admin_location, /* Wrote the /admin location? */
- wrote_conf_location, /* Wrote the /admin/conf location? */
- wrote_root_location; /* Wrote the / location? */
- int indent; /* Indentation */
-
-
- /*
- * Get form variables...
- */
- remote_printers = cgiGetVariable("REMOTE_PRINTERS") != NULL;
- share_printers = cgiGetVariable("SHARE_PRINTERS") != NULL;
- remote_admin = cgiGetVariable("REMOTE_ADMIN") != NULL;
- user_cancel_any = cgiGetVariable("USER_CANCEL_ANY") != NULL;
- debug_logging = cgiGetVariable("DEBUG_LOGGING") != NULL;
/*
* Locate the cupsd.conf file...
if ((server_root = getenv("CUPS_SERVERROOT")) == NULL)
server_root = CUPS_SERVERROOT;
- snprintf(line, sizeof(line), "%s/cupsd.conf", server_root);
+ snprintf(filename, sizeof(filename), "%s/cupsd.conf", server_root);
/*
- * Open the cupsd.conf file...
+ * Figure out the size...
*/
- if ((cupsd = cupsFileOpen(line, "r")) == NULL)
+ if (stat(filename, &info))
{
- /*
- * Unable to open - log an error...
- */
-
- cgiStartHTML(cgiText(_("Change Settings")));
- cgiSetVariable("MESSAGE", cgiText(_("Unable to change server settings:")));
+ cgiStartHTML(cgiText(_("Edit Configuration File")));
+ cgiSetVariable("MESSAGE",
+ cgiText(_("Unable to access cupsd.conf file")));
cgiSetVariable("ERROR", strerror(errno));
cgiCopyTemplateLang("error.tmpl");
cgiEndHTML();
-
- perror(line);
+
+ perror(filename);
return;
}
- /*
- * Create a temporary file for the new cupsd.conf file...
- */
-
- if ((tempfd = cupsTempFd(tempfile, sizeof(tempfile))) < 0)
+ if (info.st_size > (1024 * 1024))
{
- cgiStartHTML(cgiText(_("Change Settings")));
- cgiSetVariable("MESSAGE", cgiText(_("Unable to change server settings:")));
- cgiSetVariable("ERROR", strerror(errno));
+ cgiStartHTML(cgiText(_("Edit Configuration File")));
+ cgiSetVariable("MESSAGE",
+ cgiText(_("Unable to access cupsd.conf file")));
+ cgiSetVariable("ERROR",
+ cgiText(_("Unable to edit cupsd.conf files larger than "
+ "1MB")));
cgiCopyTemplateLang("error.tmpl");
cgiEndHTML();
-
- perror(tempfile);
- cupsFileClose(cupsd);
+
+ fprintf(stderr, "ERROR: \"%s\" too large (%ld) to edit!\n", filename,
+ (long)info.st_size);
return;
}
- if ((temp = cupsFileOpenFd(tempfd, "w")) == NULL)
+ /*
+ * Open the cupsd.conf file...
+ */
+
+ if ((cupsd = cupsFileOpen(filename, "r")) == NULL)
{
- cgiStartHTML(cgiText(_("Change Settings")));
- cgiSetVariable("MESSAGE", cgiText(_("Unable to change server settings:")));
+ /*
+ * Unable to open - log an error...
+ */
+
+ cgiStartHTML(cgiText(_("Edit Configuration File")));
+ cgiSetVariable("MESSAGE",
+ cgiText(_("Unable to access cupsd.conf file")));
cgiSetVariable("ERROR", strerror(errno));
cgiCopyTemplateLang("error.tmpl");
cgiEndHTML();
-
- perror(tempfile);
- close(tempfd);
- unlink(tempfile);
- cupsFileClose(cupsd);
+
+ perror(filename);
return;
}
/*
- * Copy the old file to the new, making changes along the way...
+ * Allocate memory and load the file into a string buffer...
+ */
+
+ if ((buffer = calloc(1, (size_t)info.st_size + 1)) != NULL)
+ {
+ cupsFileRead(cupsd, buffer, (size_t)info.st_size);
+ cgiSetVariable("CUPSDCONF", buffer);
+ free(buffer);
+ }
+
+ cupsFileClose(cupsd);
+
+ /*
+ * Then get the default cupsd.conf file and put that into a string as
+ * well...
*/
- in_admin_location = 0;
- in_cancel_job = 0;
- in_conf_location = 0;
- in_policy = 0;
- in_root_location = 0;
- linenum = 0;
- wrote_admin_location = 0;
- wrote_browsing = 0;
- wrote_conf_location = 0;
- wrote_loglevel = 0;
- wrote_policy = 0;
- wrote_port_listen = 0;
- wrote_root_location = 0;
- indent = 0;
-
- while (cupsFileGetConf(cupsd, line, sizeof(line), &value, &linenum))
- {
- if (!strcasecmp(line, "Port") || !strcasecmp(line, "Listen"))
+ strlcat(filename, ".default", sizeof(filename));
+
+ if (!stat(filename, &info) && info.st_size < (1024 * 1024) &&
+ (cupsd = cupsFileOpen(filename, "r")) != NULL)
+ {
+ if ((buffer = calloc(1, 2 * (size_t)info.st_size + 1)) != NULL)
{
- if (!wrote_port_listen)
- {
- wrote_port_listen = 1;
+ bufend = buffer + 2 * info.st_size - 1;
- if (share_printers || remote_admin)
+ for (bufptr = buffer;
+ bufptr < bufend && (ch = cupsFileGetChar(cupsd)) != EOF;)
+ {
+ if (ch == '\\' || ch == '\"')
{
- cupsFilePuts(temp, "# Allow remote access\n");
- cupsFilePrintf(temp, "Listen *:%d\n", ippPort());
+ *bufptr++ = '\\';
+ *bufptr++ = (char)ch;
}
- else
+ else if (ch == '\n')
{
- cupsFilePuts(temp, "# Only listen for connections from the local machine.\n");
- cupsFilePrintf(temp, "Listen localhost:%d\n", ippPort());
+ *bufptr++ = '\\';
+ *bufptr++ = 'n';
}
-
-#ifdef CUPS_DEFAULT_DOMAINSOCKET
- cupsFilePuts(temp, "Listen " CUPS_DEFAULT_DOMAINSOCKET "\n");
-#endif /* CUPS_DEFAULT_DOMAINSOCKET */
- }
- }
- else if (!strcasecmp(line, "Browsing") ||
- !strcasecmp(line, "BrowseAddress") ||
- !strcasecmp(line, "BrowseAllow") ||
- !strcasecmp(line, "BrowseDeny") ||
- !strcasecmp(line, "BrowseOrder"))
- {
- if (!wrote_browsing)
- {
- wrote_browsing = 1;
-
- if (remote_printers || share_printers)
- {
- if (remote_printers && share_printers)
- cupsFilePuts(temp, "# Enable printer sharing and shared printers.\n");
- else if (remote_printers)
- cupsFilePuts(temp, "# Show shared printers on the local network.\n");
- else
- cupsFilePuts(temp, "# Share local printers on the local network.\n");
-
- cupsFilePuts(temp, "Browsing On\n");
- cupsFilePuts(temp, "BrowseOrder allow,deny\n");
-
- if (remote_printers)
- cupsFilePuts(temp, "BrowseAllow @LOCAL\n");
-
- if (share_printers)
- cupsFilePuts(temp, "BrowseAddress @LOCAL\n");
- }
- else
+ else if (ch == '\t')
{
- cupsFilePuts(temp, "# Disable printer sharing and shared printers.\n");
- cupsFilePuts(temp, "Browsing Off\n");
+ *bufptr++ = '\\';
+ *bufptr++ = 't';
}
+ else if (ch >= ' ')
+ *bufptr++ = (char)ch;
}
- }
- else if (!strcasecmp(line, "LogLevel"))
- {
- wrote_loglevel = 1;
- if (debug_logging)
- {
- cupsFilePuts(temp, "# Show troubleshooting information in error_log.\n");
- cupsFilePuts(temp, "LogLevel debug\n");
- }
- else
- {
- cupsFilePuts(temp, "# Show general information in error_log.\n");
- cupsFilePuts(temp, "LogLevel info\n");
- }
- }
- else if (!strcasecmp(line, "<Policy") && !strcasecmp(value, "default"))
- {
- in_policy = 1;
+ *bufptr = '\0';
- cupsFilePrintf(temp, "%s %s>\n", line, value);
- indent += 2;
+ cgiSetVariable("CUPSDCONF_DEFAULT", buffer);
+ free(buffer);
}
- else if (!strcasecmp(line, "</Policy>"))
- {
- indent -= 2;
- if (!wrote_policy)
- {
- wrote_policy = 1;
-
- if (!user_cancel_any)
- cupsFilePuts(temp, " # Only the owner or an administrator can cancel a job...\n"
- " <Limit Cancel-Job>\n"
- " Order deny,allow\n"
- " Allow @SYSTEM\n"
- " Allow @OWNER\n"
- " </Limit>\n");
- }
- in_policy = 0;
+ cupsFileClose(cupsd);
+ }
- cupsFilePuts(temp, "</Policy>\n");
- }
- else if (!strcasecmp(line, "<Location"))
- {
- indent += 2;
- if (!strcmp(value, "/admin"))
- in_admin_location = 1;
- if (!strcmp(value, "/admin/conf"))
- in_conf_location = 1;
- else if (!strcmp(value, "/"))
- in_root_location = 1;
-
- cupsFilePrintf(temp, "%s %s>\n", line, value);
- }
- else if (!strcasecmp(line, "</Location>"))
- {
- indent -= 2;
- if (in_admin_location)
- {
- wrote_admin_location = 1;
+ /*
+ * Show the current config file...
+ */
- if (remote_admin)
- cupsFilePuts(temp, " # Allow remote administration...\n");
- else
- cupsFilePuts(temp, " # Restrict access to the admin pages...\n");
+ cgiStartHTML(cgiText(_("Edit Configuration File")));
- cupsFilePuts(temp, " Order allow,deny\n");
-
- if (remote_admin)
- cupsFilePuts(temp, " Allow @LOCAL\n");
- else
- cupsFilePuts(temp, " Allow localhost\n");
- }
- else if (in_conf_location)
- {
- wrote_conf_location = 1;
-
- if (remote_admin)
- cupsFilePuts(temp, " # Allow remote access to the configuration files...\n");
- else
- cupsFilePuts(temp, " # Restrict access to the configuration files...\n");
-
- cupsFilePuts(temp, " Order allow,deny\n");
+ cgiCopyTemplateLang("edit-config.tmpl");
- if (remote_admin)
- cupsFilePuts(temp, " Allow @LOCAL\n");
- else
- cupsFilePuts(temp, " Allow localhost\n");
- }
- else if (in_root_location)
- {
- wrote_root_location = 1;
-
- if (remote_admin && share_printers)
- cupsFilePuts(temp, " # Allow shared printing and remote administration...\n");
- else if (remote_admin)
- cupsFilePuts(temp, " # Allow remote administration...\n");
- else if (share_printers)
- cupsFilePuts(temp, " # Allow shared printing...\n");
- else
- cupsFilePuts(temp, " # Restrict access to the server...\n");
+ cgiEndHTML();
+ }
+}
- cupsFilePuts(temp, " Order allow,deny\n");
- if (remote_admin || share_printers)
- cupsFilePuts(temp, " Allow @LOCAL\n");
- else
- cupsFilePuts(temp, " Allow localhost\n");
- }
+/*
+ * 'do_delete_class()' - Delete a class.
+ */
- in_admin_location = 0;
- in_conf_location = 0;
- in_root_location = 0;
+static void
+do_delete_class(http_t *http) /* I - HTTP connection */
+{
+ ipp_t *request; /* IPP request */
+ char uri[HTTP_MAX_URI]; /* Job URI */
+ const char *pclass; /* Printer class name */
- cupsFilePuts(temp, "</Location>\n");
- }
- else if (!strcasecmp(line, "<Limit") && in_policy)
- {
- /*
- * See if the policy limit is for the Cancel-Job operation...
- */
- char *valptr; /* Pointer into value */
+ /*
+ * Get form variables...
+ */
+ if (cgiGetVariable("CONFIRM") == NULL)
+ {
+ cgiStartHTML(cgiText(_("Delete Class")));
+ cgiCopyTemplateLang("class-confirm.tmpl");
+ cgiEndHTML();
+ return;
+ }
- indent += 2;
+ if ((pclass = cgiGetVariable("PRINTER_NAME")) != NULL)
+ httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
+ "localhost", 0, "/classes/%s", pclass);
+ else
+ {
+ cgiStartHTML(cgiText(_("Delete Class")));
+ cgiSetVariable("ERROR", cgiText(_("Missing form variable")));
+ cgiCopyTemplateLang("error.tmpl");
+ cgiEndHTML();
+ return;
+ }
- if (!strcasecmp(value, "cancel-job"))
- {
- /*
- * Don't write anything for this limit section...
- */
+ /*
+ * Build a CUPS_DELETE_CLASS request, which requires the following
+ * attributes:
+ *
+ * attributes-charset
+ * attributes-natural-language
+ * printer-uri
+ */
- in_cancel_job = 2;
- }
- else
- {
- cupsFilePrintf(temp, " %s", line);
+ request = ippNewRequest(CUPS_DELETE_CLASS);
- while (*value)
- {
- for (valptr = value; !isspace(*valptr & 255) && *valptr; valptr ++);
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
+ NULL, uri);
- if (*valptr)
- *valptr++ = '\0';
+ /*
+ * Do the request and get back a response...
+ */
- if (!strcasecmp(value, "cancel-job"))
- {
- /*
- * Write everything except for this definition...
- */
+ ippDelete(cupsDoRequest(http, request, "/admin/"));
- in_cancel_job = 1;
- }
- else
- cupsFilePrintf(temp, " %s", value);
+ /*
+ * Show the results...
+ */
- for (value = valptr; isspace(*value & 255); value ++);
- }
+ if (cupsLastError() == IPP_NOT_AUTHORIZED)
+ {
+ puts("Status: 401\n");
+ exit(0);
+ }
+ else if (cupsLastError() <= IPP_OK_CONFLICT)
+ {
+ /*
+ * Redirect successful updates back to the classes page...
+ */
- cupsFilePuts(temp, ">\n");
- }
- }
- else if (!strcasecmp(line, "</Limit>") && in_cancel_job)
- {
- indent -= 2;
+ cgiSetVariable("refresh_page", "5;URL=/admin/?OP=redirect&URL=/classes");
+ }
- if (in_cancel_job == 1)
- cupsFilePuts(temp, " </Limit>\n");
+ cgiStartHTML(cgiText(_("Delete Class")));
- wrote_policy = 1;
+ if (cupsLastError() > IPP_OK_CONFLICT)
+ cgiShowIPPError(_("Unable to delete class"));
+ else
+ cgiCopyTemplateLang("class-deleted.tmpl");
- if (!user_cancel_any)
- cupsFilePuts(temp, " # Only the owner or an administrator can cancel a job...\n"
- " <Limit Cancel-Job>\n"
- " Order deny,allow\n"
- " Require user @OWNER @SYSTEM\n"
- " </Limit>\n");
+ cgiEndHTML();
+}
- in_cancel_job = 0;
- }
- else if ((in_admin_location || in_conf_location || in_root_location) &&
- (!strcasecmp(line, "Allow") || !strcasecmp(line, "Deny") ||
- !strcasecmp(line, "Order")))
- continue;
- else if (in_cancel_job == 2)
- continue;
- else if (!strcasecmp(line, "<Limit") && value)
- cupsFilePrintf(temp, " %s %s>\n", line, value);
- else if (line[0] == '<')
- {
- if (value)
- {
- cupsFilePrintf(temp, "%*s%s %s>\n", indent, "", line, value);
- indent += 2;
- }
- else
- {
- if (line[1] == '/')
- indent -= 2;
- cupsFilePrintf(temp, "%*s%s\n", indent, "", line);
- }
- }
- else if (value)
- cupsFilePrintf(temp, "%*s%s %s\n", indent, "", line, value);
- else
- cupsFilePrintf(temp, "%*s%s\n", indent, "", line);
- }
+/*
+ * 'do_delete_printer()' - Delete a printer.
+ */
- /*
- * Write any missing info...
- */
+static void
+do_delete_printer(http_t *http) /* I - HTTP connection */
+{
+ ipp_t *request; /* IPP request */
+ char uri[HTTP_MAX_URI]; /* Job URI */
+ const char *printer; /* Printer printer name */
- if (!wrote_browsing)
- {
- if (remote_printers || share_printers)
- {
- if (remote_printers && share_printers)
- cupsFilePuts(temp, "# Enable printer sharing and shared printers.\n");
- else if (remote_printers)
- cupsFilePuts(temp, "# Show shared printers on the local network.\n");
- else
- cupsFilePuts(temp, "# Share local printers on the local network.\n");
- cupsFilePuts(temp, "Browsing On\n");
- cupsFilePuts(temp, "BrowseOrder allow,deny\n");
+ /*
+ * Get form variables...
+ */
- if (remote_printers)
- cupsFilePuts(temp, "BrowseAllow @LOCAL\n");
+ if (cgiGetVariable("CONFIRM") == NULL)
+ {
+ cgiStartHTML(cgiText(_("Delete Printer")));
+ cgiCopyTemplateLang("printer-confirm.tmpl");
+ cgiEndHTML();
+ return;
+ }
- if (share_printers)
- cupsFilePuts(temp, "BrowseAddress @LOCAL\n");
- }
- else
- {
- cupsFilePuts(temp, "# Disable printer sharing and shared printers.\n");
- cupsFilePuts(temp, "Browsing Off\n");
- }
- }
+ if ((printer = cgiGetVariable("PRINTER_NAME")) != NULL)
+ httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
+ "localhost", 0, "/printers/%s", printer);
+ else
+ {
+ cgiStartHTML(cgiText(_("Delete Printer")));
+ cgiSetVariable("ERROR", cgiText(_("Missing form variable")));
+ cgiCopyTemplateLang("error.tmpl");
+ cgiEndHTML();
+ return;
+ }
- if (!wrote_loglevel)
- {
- if (debug_logging)
- {
- cupsFilePuts(temp, "# Show troubleshooting information in error_log.\n");
- cupsFilePuts(temp, "LogLevel debug\n");
- }
- else
- {
- cupsFilePuts(temp, "# Show general information in error_log.\n");
- cupsFilePuts(temp, "LogLevel info\n");
- }
- }
+ /*
+ * Build a CUPS_DELETE_PRINTER request, which requires the following
+ * attributes:
+ *
+ * attributes-charset
+ * attributes-natural-language
+ * printer-uri
+ */
- if (!wrote_port_listen)
- {
- if (share_printers || remote_admin)
- {
- cupsFilePuts(temp, "# Allow remote access\n");
- cupsFilePrintf(temp, "Listen *:%d\n", ippPort());
- }
- else
- {
- cupsFilePuts(temp, "# Only listen for connections from the local machine.\n");
- cupsFilePrintf(temp, "Listen localhost:%d\n", ippPort());
- }
+ request = ippNewRequest(CUPS_DELETE_PRINTER);
-#ifdef CUPS_DEFAULT_DOMAINSOCKET
- cupsFilePuts(temp, "Listen " CUPS_DEFAULT_DOMAINSOCKET "\n");
-#endif /* CUPS_DEFAULT_DOMAINSOCKET */
- }
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
+ NULL, uri);
- if (!wrote_root_location)
- {
- if (remote_admin && share_printers)
- cupsFilePuts(temp, "# Allow shared printing and remote administration...\n");
- else if (remote_admin)
- cupsFilePuts(temp, "# Allow remote administration...\n");
- else if (share_printers)
- cupsFilePuts(temp, "# Allow shared printing...\n");
- else
- cupsFilePuts(temp, "# Restrict access to the server...\n");
+ /*
+ * Do the request and get back a response...
+ */
- cupsFilePuts(temp, "<Location />\n"
- " Order allow,deny\n");
+ ippDelete(cupsDoRequest(http, request, "/admin/"));
- if (remote_admin || share_printers)
- cupsFilePuts(temp, " Allow @LOCAL\n");
- else
- cupsFilePuts(temp, " Allow localhost\n");
+ /*
+ * Show the results...
+ */
- cupsFilePuts(temp, "</Location>\n");
- }
+ if (cupsLastError() == IPP_NOT_AUTHORIZED)
+ {
+ puts("Status: 401\n");
+ exit(0);
+ }
+ else if (cupsLastError() <= IPP_OK_CONFLICT)
+ {
+ /*
+ * Redirect successful updates back to the printers page...
+ */
- if (!wrote_admin_location)
- {
- if (remote_admin)
- cupsFilePuts(temp, "# Allow remote administration...\n");
- else
- cupsFilePuts(temp, "# Restrict access to the admin pages...\n");
+ cgiSetVariable("refresh_page", "5;URL=/admin/?OP=redirect&URL=/printers");
+ }
- cupsFilePuts(temp, "<Location /admin>\n"
- " Order allow,deny\n");
+ cgiStartHTML(cgiText(_("Delete Printer")));
- if (remote_admin)
- cupsFilePuts(temp, " Allow @LOCAL\n");
- else
- cupsFilePuts(temp, " Allow localhost\n");
+ if (cupsLastError() > IPP_OK_CONFLICT)
+ cgiShowIPPError(_("Unable to delete printer"));
+ else
+ cgiCopyTemplateLang("printer-deleted.tmpl");
- cupsFilePuts(temp, "</Location>\n");
- }
+ cgiEndHTML();
+}
- if (!wrote_conf_location)
- {
- if (remote_admin)
- cupsFilePuts(temp, "# Allow remote access to the configuration files...\n");
- else
- cupsFilePuts(temp, "# Restrict access to the configuration files...\n");
- cupsFilePuts(temp, "<Location /admin/conf>\n"
- " AuthType Basic\n"
- " Require user @SYSTEM\n"
- " Order allow,deny\n");
+/*
+ * 'do_list_printers()' - List available printers.
+ */
- if (remote_admin)
- cupsFilePuts(temp, " Allow @LOCAL\n");
- else
- cupsFilePuts(temp, " Allow localhost\n");
-
- cupsFilePuts(temp, "</Location>\n");
- }
-
- if (!wrote_policy)
- {
- cupsFilePuts(temp, "<Policy default>\n"
- " # Job-related operations must be done by the owner or an adminstrator...\n"
- " <Limit Send-Document Send-URI Hold-Job Release-Job "
- "Restart-Job Purge-Jobs Set-Job-Attributes "
- "Create-Job-Subscription Renew-Subscription "
- "Cancel-Subscription Get-Notifications Reprocess-Job "
- "Cancel-Current-Job Suspend-Current-Job Resume-Job "
- "CUPS-Move-Job>\n"
- " Require user @OWNER @SYSTEM\n"
- " Order deny,allow\n"
- " </Limit>\n"
- " # All administration operations require an adminstrator to authenticate...\n"
- " <Limit Pause-Printer Resume-Printer "
- "Set-Printer-Attributes Enable-Printer "
- "Disable-Printer Pause-Printer-After-Current-Job "
- "Hold-New-Jobs Release-Held-New-Jobs Deactivate-Printer "
- "Activate-Printer Restart-Printer Shutdown-Printer "
- "Startup-Printer Promote-Job Schedule-Job-After "
- "CUPS-Add-Printer CUPS-Delete-Printer "
- "CUPS-Add-Class CUPS-Delete-Class "
- "CUPS-Accept-Jobs CUPS-Reject-Jobs "
- "CUPS-Set-Default CUPS-Add-Device CUPS-Delete-Device>\n"
- " AuthType Basic\n"
- " Require user @SYSTEM\n"
- " Order deny,allow\n"
- "</Limit>\n");
-
- if (!user_cancel_any)
- cupsFilePuts(temp, " # Only the owner or an administrator can cancel a job...\n"
- " <Limit Cancel-Job>\n"
- " Require user @OWNER @SYSTEM\n"
- " Order deny,allow\n"
- " </Limit>\n");
-
- cupsFilePuts(temp, " <Limit All>\n"
- " Order deny,allow\n"
- " </Limit>\n"
- "</Policy>\n");
- }
+static void
+do_list_printers(http_t *http) /* I - HTTP connection */
+{
+ ipp_t *request, /* IPP request */
+ *response; /* IPP response */
+ ipp_attribute_t *attr; /* IPP attribute */
- cupsFileClose(cupsd);
- cupsFileClose(temp);
- /*
- * Upload the configuration file to the server...
- */
+ cgiStartHTML(cgiText(_("List Available Printers")));
+ fflush(stdout);
- status = cupsPutFile(http, "/admin/conf/cupsd.conf", tempfile);
+ /*
+ * Get the list of printers and their devices...
+ */
- if (status != HTTP_CREATED)
- {
- cgiSetVariable("MESSAGE", cgiText(_("Unable to upload cupsd.conf file:")));
- cgiSetVariable("ERROR", httpStatus(status));
- cgiStartHTML(cgiText(_("Change Settings")));
- cgiCopyTemplateLang("error.tmpl");
- }
- else
- {
- cgiSetVariable("refresh_page", "5;/admin/?OP=redirect");
+ request = ippNewRequest(CUPS_GET_PRINTERS);
- cgiStartHTML(cgiText(_("Change Settings")));
- cgiCopyTemplateLang("restart.tmpl");
- }
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
+ "requested-attributes", NULL, "device-uri");
- cgiEndHTML();
+ ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_ENUM, "printer-type",
+ CUPS_PRINTER_LOCAL);
+ ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_ENUM, "printer-type-mask",
+ CUPS_PRINTER_LOCAL);
- unlink(tempfile);
- }
- else if (cgiIsPOST())
+ if ((response = cupsDoRequest(http, request, "/")) != NULL)
{
/*
- * Save hand-edited config file...
+ * Got the printer list, now load the devices...
*/
- http_status_t status; /* PUT status */
- char tempfile[1024]; /* Temporary new cupsd.conf */
- int tempfd; /* Temporary file descriptor */
- cups_file_t *temp; /* Temporary file */
- const char *start, /* Start of line */
- *end; /* End of line */
+ int i; /* Looping var */
+ cups_array_t *printer_devices; /* Printer devices for local printers */
+ char *printer_device; /* Current printer device */
/*
- * Create a temporary file for the new cupsd.conf file...
+ * Allocate an array and copy the device strings...
*/
- if ((tempfd = cupsTempFd(tempfile, sizeof(tempfile))) < 0)
+ printer_devices = cupsArrayNew((cups_array_func_t)strcmp, NULL);
+
+ for (attr = ippFindAttribute(response, "device-uri", IPP_TAG_URI);
+ attr;
+ attr = ippFindNextAttribute(response, "device-uri", IPP_TAG_URI))
{
- cgiStartHTML(cgiText(_("Edit Configuration File")));
- cgiSetVariable("MESSAGE", cgiText(_("Unable to create temporary file:")));
- cgiSetVariable("ERROR", strerror(errno));
- cgiCopyTemplateLang("error.tmpl");
- cgiEndHTML();
-
- perror(tempfile);
- return;
- }
-
- if ((temp = cupsFileOpenFd(tempfd, "w")) == NULL)
- {
- cgiStartHTML(cgiText(_("Edit Configuration File")));
- cgiSetVariable("MESSAGE", cgiText(_("Unable to create temporary file:")));
- cgiSetVariable("ERROR", strerror(errno));
- cgiCopyTemplateLang("error.tmpl");
- cgiEndHTML();
-
- perror(tempfile);
- close(tempfd);
- unlink(tempfile);
- return;
+ cupsArrayAdd(printer_devices, strdup(attr->values[0].string.text));
}
/*
- * Copy the cupsd.conf text from the form variable...
+ * Free the printer list and get the device list...
*/
- start = cgiGetVariable("CUPSDCONF");
- while (start)
- {
- if ((end = strstr(start, "\r\n")) == NULL)
- if ((end = strstr(start, "\n")) == NULL)
- end = start + strlen(start);
+ ippDelete(response);
- cupsFileWrite(temp, start, end - start);
- cupsFilePutChar(temp, '\n');
+ request = ippNewRequest(CUPS_GET_DEVICES);
- if (*end == '\r')
- start = end + 2;
- else if (*end == '\n')
- start = end + 1;
- else
- start = NULL;
- }
+ if ((response = cupsDoRequest(http, request, "/")) != NULL)
+ {
+ /*
+ * Got the device list, let's parse it...
+ */
- cupsFileClose(temp);
+ const char *device_uri, /* device-uri attribute value */
+ *device_make_and_model, /* device-make-and-model value */
+ *device_info; /* device-info value */
- /*
- * Upload the configuration file to the server...
- */
- status = cupsPutFile(http, "/admin/conf/cupsd.conf", tempfile);
+ for (i = 0, attr = response->attrs; attr; attr = attr->next)
+ {
+ /*
+ * Skip leading attributes until we hit a device...
+ */
- if (status != HTTP_CREATED)
- {
- cgiSetVariable("MESSAGE", cgiText(_("Unable to upload cupsd.conf file:")));
- cgiSetVariable("ERROR", httpStatus(status));
+ while (attr && attr->group_tag != IPP_TAG_PRINTER)
+ attr = attr->next;
- cgiStartHTML(cgiText(_("Edit Configuration File")));
- cgiCopyTemplateLang("error.tmpl");
- }
- else
- {
- cgiSetVariable("refresh_page", "5;/admin/?OP=redirect");
+ if (!attr)
+ break;
- cgiStartHTML(cgiText(_("Edit Configuration File")));
- cgiCopyTemplateLang("restart.tmpl");
- }
+ /*
+ * Pull the needed attributes from this device...
+ */
- cgiEndHTML();
+ device_info = NULL;
+ device_make_and_model = NULL;
+ device_uri = NULL;
- unlink(tempfile);
- }
- else
- {
- struct stat info; /* cupsd.conf information */
- cups_file_t *cupsd; /* cupsd.conf file */
- char *buffer; /* Buffer for entire file */
- char filename[1024]; /* Filename */
- const char *server_root; /* Location of config files */
+ while (attr && attr->group_tag == IPP_TAG_PRINTER)
+ {
+ if (!strcmp(attr->name, "device-info") &&
+ attr->value_tag == IPP_TAG_TEXT)
+ device_info = attr->values[0].string.text;
+ if (!strcmp(attr->name, "device-make-and-model") &&
+ attr->value_tag == IPP_TAG_TEXT)
+ device_make_and_model = attr->values[0].string.text;
- /*
- * Locate the cupsd.conf file...
- */
+ if (!strcmp(attr->name, "device-uri") &&
+ attr->value_tag == IPP_TAG_URI)
+ device_uri = attr->values[0].string.text;
- if ((server_root = getenv("CUPS_SERVERROOT")) == NULL)
- server_root = CUPS_SERVERROOT;
+ attr = attr->next;
+ }
- snprintf(filename, sizeof(filename), "%s/cupsd.conf", server_root);
+ /*
+ * See if we have everything needed...
+ */
- /*
- * Figure out the size...
- */
+ if (device_info && device_make_and_model && device_uri &&
+ _cups_strcasecmp(device_make_and_model, "unknown") &&
+ strchr(device_uri, ':'))
+ {
+ /*
+ * Yes, now see if there is already a printer for this
+ * device...
+ */
- if (stat(filename, &info))
- {
- cgiStartHTML(cgiText(_("Edit Configuration File")));
- cgiSetVariable("MESSAGE", cgiText(_("Unable to access cupsd.conf file:")));
- cgiSetVariable("ERROR", strerror(errno));
- cgiCopyTemplateLang("error.tmpl");
- cgiEndHTML();
+ if (!cupsArrayFind(printer_devices, (void *)device_uri))
+ {
+ /*
+ * Not found, so it must be a new printer...
+ */
- perror(filename);
- return;
- }
+ char option[1024], /* Form variables for this device */
+ *option_ptr; /* Pointer into string */
+ const char *ptr; /* Pointer into device string */
- if (info.st_size > (1024 * 1024))
- {
- cgiStartHTML(cgiText(_("Edit Configuration File")));
- cgiSetVariable("MESSAGE", cgiText(_("Unable to access cupsd.conf file:")));
- cgiSetVariable("ERROR",
- cgiText(_("Unable to edit cupsd.conf files larger than "
- "1MB!")));
- cgiCopyTemplateLang("error.tmpl");
- cgiEndHTML();
- fprintf(stderr, "ERROR: \"%s\" too large (%ld) to edit!\n", filename,
- (long)info.st_size);
- return;
- }
+ /*
+ * Format the printer name variable for this device...
+ *
+ * We use the device-info string first, then device-uri,
+ * and finally device-make-and-model to come up with a
+ * suitable name.
+ */
- /*
- * Open the cupsd.conf file...
- */
+ if (_cups_strncasecmp(device_info, "unknown", 7))
+ ptr = device_info;
+ else if ((ptr = strstr(device_uri, "://")) != NULL)
+ ptr += 3;
+ else
+ ptr = device_make_and_model;
- if ((cupsd = cupsFileOpen(filename, "r")) == NULL)
- {
- /*
- * Unable to open - log an error...
- */
+ for (option_ptr = option;
+ option_ptr < (option + sizeof(option) - 1) && *ptr;
+ ptr ++)
+ if (isalnum(*ptr & 255) || *ptr == '_' || *ptr == '-' ||
+ *ptr == '.')
+ *option_ptr++ = *ptr;
+ else if ((*ptr == ' ' || *ptr == '/') && option_ptr > option &&
+ option_ptr[-1] != '_')
+ *option_ptr++ = '_';
+ else if (*ptr == '?' || *ptr == '(')
+ break;
- cgiStartHTML(cgiText(_("Edit Configuration File")));
- cgiSetVariable("MESSAGE", cgiText(_("Unable to access cupsd.conf file:")));
- cgiSetVariable("ERROR", strerror(errno));
- cgiCopyTemplateLang("error.tmpl");
- cgiEndHTML();
+ *option_ptr = '\0';
- perror(filename);
- return;
- }
+ cgiSetArray("TEMPLATE_NAME", i, option);
- /*
- * Allocate memory and load the file into a string buffer...
- */
+ /*
+ * Finally, set the form variables for this printer...
+ */
- buffer = calloc(1, info.st_size + 1);
+ cgiSetArray("device_info", i, device_info);
+ cgiSetArray("device_make_and_model", i, device_make_and_model);
+ cgiSetArray("device_uri", i, device_uri);
+ i ++;
+ }
+ }
- cupsFileRead(cupsd, buffer, info.st_size);
- cupsFileClose(cupsd);
+ if (!attr)
+ break;
+ }
- cgiSetVariable("CUPSDCONF", buffer);
- free(buffer);
+ ippDelete(response);
- /*
- * Show the current config file...
- */
+ /*
+ * Free the device list...
+ */
- cgiStartHTML("Edit Configuration File");
+ for (printer_device = (char *)cupsArrayFirst(printer_devices);
+ printer_device;
+ printer_device = (char *)cupsArrayNext(printer_devices))
+ free(printer_device);
- printf("<!-- \"%s\" -->\n", filename);
+ cupsArrayDelete(printer_devices);
+ }
+ }
- cgiCopyTemplateLang("edit-config.tmpl");
+ /*
+ * Finally, show the printer list...
+ */
- cgiEndHTML();
- }
+ cgiCopyTemplateLang("list-available-printers.tmpl");
+
+ cgiEndHTML();
}
/*
- * 'do_delete_class()' - Delete a class...
+ * 'do_menu()' - Show the main menu.
*/
static void
-do_delete_class(http_t *http) /* I - HTTP connection */
+do_menu(http_t *http) /* I - HTTP connection */
{
- ipp_t *request; /* IPP request */
- char uri[HTTP_MAX_URI]; /* Job URI */
- const char *pclass; /* Printer class name */
+ int num_settings; /* Number of server settings */
+ cups_option_t *settings; /* Server settings */
+ const char *val; /* Setting value */
- cgiStartHTML(cgiText(_("Delete Class")));
+ /*
+ * Get the current server settings...
+ */
- if (cgiGetVariable("CONFIRM") == NULL)
+ if (!cupsAdminGetServerSettings(http, &num_settings, &settings))
{
- cgiCopyTemplateLang("class-confirm.tmpl");
- cgiEndHTML();
- return;
+ cgiSetVariable("SETTINGS_MESSAGE",
+ cgiText(_("Unable to open cupsd.conf file:")));
+ cgiSetVariable("SETTINGS_ERROR", cupsLastErrorString());
}
- if ((pclass = cgiGetVariable("PRINTER_NAME")) != NULL)
- httpAssembleURIf(uri, sizeof(uri), "ipp", NULL, "localhost", 0,
- "/classes/%s", pclass);
+ if ((val = cupsGetOption(CUPS_SERVER_DEBUG_LOGGING, num_settings,
+ settings)) != NULL && atoi(val))
+ cgiSetVariable("DEBUG_LOGGING", "CHECKED");
+
+ if ((val = cupsGetOption(CUPS_SERVER_REMOTE_ADMIN, num_settings,
+ settings)) != NULL && atoi(val))
+ cgiSetVariable("REMOTE_ADMIN", "CHECKED");
+
+ if ((val = cupsGetOption(CUPS_SERVER_REMOTE_ANY, num_settings,
+ settings)) != NULL && atoi(val))
+ cgiSetVariable("REMOTE_ANY", "CHECKED");
+
+ if ((val = cupsGetOption(CUPS_SERVER_SHARE_PRINTERS, num_settings,
+ settings)) != NULL && atoi(val))
+ cgiSetVariable("SHARE_PRINTERS", "CHECKED");
+
+ if ((val = cupsGetOption(CUPS_SERVER_USER_CANCEL_ANY, num_settings,
+ settings)) != NULL && atoi(val))
+ cgiSetVariable("USER_CANCEL_ANY", "CHECKED");
+
+#ifdef HAVE_GSSAPI
+ cgiSetVariable("HAVE_GSSAPI", "1");
+
+ if ((val = cupsGetOption("DefaultAuthType", num_settings,
+ settings)) != NULL && !_cups_strcasecmp(val, "Negotiate"))
+ cgiSetVariable("KERBEROS", "CHECKED");
else
+#endif /* HAVE_GSSAPI */
+ cgiSetVariable("KERBEROS", "");
+
+ if ((val = cupsGetOption("BrowseWebIF", num_settings,
+ settings)) == NULL)
+ val = "No";
+
+ if (!_cups_strcasecmp(val, "yes") || !_cups_strcasecmp(val, "on") ||
+ !_cups_strcasecmp(val, "true"))
+ cgiSetVariable("BROWSE_WEB_IF", "CHECKED");
+
+ if ((val = cupsGetOption("PreserveJobHistory", num_settings,
+ settings)) == NULL)
+ val = "Yes";
+
+ if (val &&
+ (!_cups_strcasecmp(val, "0") || !_cups_strcasecmp(val, "no") ||
+ !_cups_strcasecmp(val, "off") || !_cups_strcasecmp(val, "false") ||
+ !_cups_strcasecmp(val, "disabled")))
{
- cgiSetVariable("ERROR", cgiText(_("Missing form variable!")));
- cgiCopyTemplateLang("error.tmpl");
- cgiEndHTML();
- return;
+ cgiSetVariable("PRESERVE_JOB_HISTORY", "0");
+ cgiSetVariable("PRESERVE_JOB_FILES", "0");
}
+ else
+ {
+ cgiSetVariable("PRESERVE_JOBS", "CHECKED");
+ cgiSetVariable("PRESERVE_JOB_HISTORY", val);
- /*
- * Build a CUPS_DELETE_CLASS request, which requires the following
- * attributes:
- *
- * attributes-charset
- * attributes-natural-language
- * printer-uri
- */
+ if ((val = cupsGetOption("PreserveJobFiles", num_settings,
+ settings)) == NULL)
+ val = "1d";
- request = ippNewRequest(CUPS_DELETE_CLASS);
+ cgiSetVariable("PRESERVE_JOB_FILES", val);
- ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
- NULL, uri);
+ }
+
+ if ((val = cupsGetOption("MaxClients", num_settings, settings)) == NULL)
+ val = "100";
+
+ cgiSetVariable("MAX_CLIENTS", val);
+
+ if ((val = cupsGetOption("MaxJobs", num_settings, settings)) == NULL)
+ val = "500";
+
+ cgiSetVariable("MAX_JOBS", val);
+
+ if ((val = cupsGetOption("MaxLogSize", num_settings, settings)) == NULL)
+ val = "1m";
+
+ cgiSetVariable("MAX_LOG_SIZE", val);
+
+ cupsFreeOptions(num_settings, settings);
/*
- * Do the request and get back a response...
+ * Finally, show the main menu template...
*/
- ippDelete(cupsDoRequest(http, request, "/admin/"));
+ cgiStartHTML(cgiText(_("Administration")));
- if (cupsLastError() > IPP_OK_CONFLICT)
- cgiShowIPPError(_("Unable to delete class:"));
- else
- cgiCopyTemplateLang("class-deleted.tmpl");
+ cgiCopyTemplateLang("admin.tmpl");
cgiEndHTML();
}
/*
- * 'do_delete_printer()' - Delete a printer...
+ * 'do_set_allowed_users()' - Set the allowed/denied users for a queue.
*/
static void
-do_delete_printer(http_t *http) /* I - HTTP connection */
+do_set_allowed_users(http_t *http) /* I - HTTP connection */
{
- ipp_t *request; /* IPP request */
- char uri[HTTP_MAX_URI]; /* Job URI */
- const char *printer; /* Printer printer name */
-
+ int i; /* Looping var */
+ ipp_t *request, /* IPP request */
+ *response; /* IPP response */
+ char uri[HTTP_MAX_URI]; /* Printer URI */
+ const char *printer, /* Printer name (purge-jobs) */
+ *is_class, /* Is a class? */
+ *users, /* List of users or groups */
+ *type; /* Allow/deny type */
+ int num_users; /* Number of users */
+ char *ptr, /* Pointer into users string */
+ *end, /* Pointer to end of users string */
+ quote; /* Quote character */
+ ipp_attribute_t *attr; /* Attribute */
+ static const char * const attrs[] = /* Requested attributes */
+ {
+ "requesting-user-name-allowed",
+ "requesting-user-name-denied"
+ };
- cgiStartHTML(cgiText(_("Delete Printer")));
- if (cgiGetVariable("CONFIRM") == NULL)
- {
- cgiCopyTemplateLang("printer-confirm.tmpl");
- cgiEndHTML();
- return;
- }
+ is_class = cgiGetVariable("IS_CLASS");
+ printer = cgiGetVariable("PRINTER_NAME");
- if ((printer = cgiGetVariable("PRINTER_NAME")) != NULL)
- httpAssembleURIf(uri, sizeof(uri), "ipp", NULL, "localhost", 0,
- "/printers/%s", printer);
- else
+ if (!printer)
{
- cgiSetVariable("ERROR", cgiText(_("Missing form variable!")));
+ cgiSetVariable("ERROR", cgiText(_("Missing form variable")));
+ cgiStartHTML(cgiText(_("Set Allowed Users")));
cgiCopyTemplateLang("error.tmpl");
cgiEndHTML();
return;
}
- /*
- * Build a CUPS_DELETE_PRINTER request, which requires the following
- * attributes:
- *
- * attributes-charset
- * attributes-natural-language
- * printer-uri
- */
-
- request = ippNewRequest(CUPS_DELETE_PRINTER);
-
- ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
- NULL, uri);
-
- /*
- * Do the request and get back a response...
- */
-
- ippDelete(cupsDoRequest(http, request, "/admin/"));
-
- if (cupsLastError() > IPP_OK_CONFLICT)
- cgiShowIPPError(_("Unable to delete printer:"));
- else
- cgiCopyTemplateLang("printer-deleted.tmpl");
-
- cgiEndHTML();
-}
-
-
-/*
- * 'do_export()' - Export printers to Samba...
- */
-
-static void
-do_export(http_t *http) /* I - HTTP connection */
-{
- int i, j; /* Looping vars */
- ipp_t *request, /* IPP request */
- *response; /* IPP response */
- const char *username, /* Samba username */
- *password, /* Samba password */
- *export_all; /* Export all printers? */
- int export_count, /* Number of printers to export */
- printer_count; /* Number of available printers */
-
-
- /*
- * Show header...
- */
-
- cgiStartHTML(cgiText(_("Export Printers to Samba")));
-
- /*
- * Get form data...
- */
-
- username = cgiGetVariable("USERNAME");
- password = cgiGetVariable("PASSWORD");
- export_all = cgiGetVariable("EXPORT_ALL");
- export_count = cgiGetSize("EXPORT_NAME");
+ users = cgiGetVariable("users");
+ type = cgiGetVariable("type");
- if (username && *username && password && *password && export_count <= 1000)
+ if (!users || !type ||
+ (strcmp(type, "requesting-user-name-allowed") &&
+ strcmp(type, "requesting-user-name-denied")))
{
/*
- * Do export...
+ * Build a Get-Printer-Attributes request, which requires the following
+ * attributes:
+ *
+ * attributes-charset
+ * attributes-natural-language
+ * printer-uri
+ * requested-attributes
*/
- char userpass[1024], /* Username%password */
- *argv[1005]; /* Arguments */
- int argc; /* Number of arguments */
- int pid; /* Process ID of child */
- int status; /* Status of command */
+ request = ippNewRequest(IPP_GET_PRINTER_ATTRIBUTES);
+ httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
+ "localhost", 0, is_class ? "/classes/%s" : "/printers/%s",
+ printer);
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
+ NULL, uri);
- fputs("DEBUG: Export printers...\n", stderr);
+ ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
+ "requested-attributes",
+ (int)(sizeof(attrs) / sizeof(attrs[0])), NULL, attrs);
/*
- * Create the command-line for cupsaddsmb...
+ * Do the request and get back a response...
*/
- snprintf(userpass, sizeof(userpass), "%s%%%s", username, password);
+ if ((response = cupsDoRequest(http, request, "/")) != NULL)
+ {
+ cgiSetIPPVars(response, NULL, NULL, NULL, 0);
+
+ ippDelete(response);
+ }
- argv[0] = "cupsaddsmb";
- argv[1] = "-v";
- argv[2] = "-U";
- argv[3] = userpass;
- argc = 4;
+ cgiStartHTML(cgiText(_("Set Allowed Users")));
- if (export_all)
- argv[argc ++] = "-a";
- else
+ if (cupsLastError() == IPP_NOT_AUTHORIZED)
{
- for (i = 0; i < export_count; i ++)
- argv[argc ++] = (char *)cgiGetArray("EXPORT_NAME", i);
+ puts("Status: 401\n");
+ exit(0);
}
+ else if (cupsLastError() > IPP_OK_CONFLICT)
+ cgiShowIPPError(_("Unable to get printer attributes"));
+ else
+ cgiCopyTemplateLang("users.tmpl");
- argv[argc] = NULL;
-
+ cgiEndHTML();
+ }
+ else
+ {
/*
- * Run the command...
+ * Save the changes...
*/
- if ((pid = fork()) == 0)
+ for (num_users = 0, ptr = (char *)users; *ptr; num_users ++)
{
/*
- * Child goes here...
+ * Skip whitespace and commas...
*/
- close(0);
- open("/dev/null", O_RDONLY);
- close(1);
- dup(2);
-
- execvp("cupsaddsmb", argv);
- perror("ERROR: Unable to execute cupsaddsmb");
- exit(20);
- }
- else if (pid < 0)
- cgiSetVariable("ERROR", cgiText(_("Unable to fork process!")));
- else
- {
- /*
- * Parent goes here, wait for child to finish...
- */
+ while (*ptr == ',' || isspace(*ptr & 255))
+ ptr ++;
- while (wait(&status) < 0);
+ if (!*ptr)
+ break;
- if (status)
+ if (*ptr == '\'' || *ptr == '\"')
{
- char message[1024]; /* Error message */
-
+ /*
+ * Scan quoted name...
+ */
- if (WIFEXITED(status))
- {
- switch (WEXITSTATUS(status))
- {
- case 1 :
- cgiSetVariable("ERROR", cgiText(_("Unable to connect to server!")));
- break;
-
- case 2 :
- cgiSetVariable("ERROR", cgiText(_("Unable to get printer "
- "attributes!")));
- break;
-
- case 3 :
- cgiSetVariable("ERROR", cgiText(_("Unable to convert PPD file!")));
- break;
-
- case 4 :
- cgiSetVariable("ERROR", cgiText(_("Unable to copy Windows 2000 "
- "printer driver files!")));
- break;
-
- case 5 :
- cgiSetVariable("ERROR", cgiText(_("Unable to install Windows "
- "2000 printer driver files!")));
- break;
-
- case 6 :
- cgiSetVariable("ERROR", cgiText(_("Unable to copy Windows 9x "
- "printer driver files!")));
- break;
-
- case 7 :
- cgiSetVariable("ERROR", cgiText(_("Unable to install Windows "
- "9x printer driver files!")));
- break;
-
- case 8 :
- cgiSetVariable("ERROR", cgiText(_("Unable to set Windows "
- "printer driver!")));
- break;
-
- case 9 :
- cgiSetVariable("ERROR", cgiText(_("No printer drivers found!")));
- break;
-
- case 20 :
- cgiSetVariable("ERROR", cgiText(_("Unable to execute "
- "cupsaddsmb command!")));
- break;
-
- default :
- snprintf(message, sizeof(message),
- cgiText(_("cupsaddsmb failed with status %d")),
- WEXITSTATUS(status));
-
- cgiSetVariable("ERROR", message);
- break;
- }
- }
- else
- {
- snprintf(message, sizeof(message),
- cgiText(_("cupsaddsmb crashed on signal %d")),
- WTERMSIG(status));
+ quote = *ptr++;
- cgiSetVariable("ERROR", message);
- }
+ for (end = ptr; *end; end ++)
+ if (*end == quote)
+ break;
}
else
{
- cgiCopyTemplateLang("samba-exported");
- cgiEndHTML();
- return;
- }
- }
- }
- else if (username && !*username)
- cgiSetVariable("ERROR",
- cgiText(_("A Samba username is required to export "
- "printer drivers!")));
- else if (username && (!password || !*password))
- cgiSetVariable("ERROR",
- cgiText(_("A Samba password is required to export "
- "printer drivers!")));
-
- /*
- * Get list of available printers...
- */
+ /*
+ * Scan space or comma-delimited name...
+ */
- cgiSetSize("PRINTER_NAME", 0);
- cgiSetSize("PRINTER_EXPORT", 0);
+ for (end = ptr; *end; end ++)
+ if (isspace(*end & 255) || *end == ',')
+ break;
+ }
- request = ippNewRequest(CUPS_GET_PRINTERS);
+ /*
+ * Advance to the next name...
+ */
- ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_ENUM,
- "printer-type", 0);
+ ptr = end;
+ }
- ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_ENUM,
- "printer-type-mask", CUPS_PRINTER_CLASS | CUPS_PRINTER_REMOTE |
- CUPS_PRINTER_IMPLICIT);
+ /*
+ * Build a CUPS-Add-Printer/Class request, which requires the following
+ * attributes:
+ *
+ * attributes-charset
+ * attributes-natural-language
+ * printer-uri
+ * requesting-user-name-{allowed,denied}
+ */
- ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
- "requested-attributes", NULL, "printer-name");
+ request = ippNewRequest(is_class ? CUPS_ADD_CLASS : CUPS_ADD_PRINTER);
- if ((response = cupsDoRequest(http, request, "/")) != NULL)
- {
- cgiSetIPPVars(response, NULL, NULL, NULL, 0);
- ippDelete(response);
+ httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
+ "localhost", 0, is_class ? "/classes/%s" : "/printers/%s",
+ printer);
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
+ NULL, uri);
- if (!export_all)
+ if (num_users == 0)
+ ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_NAME,
+ "requesting-user-name-allowed", NULL, "all");
+ else
{
- printer_count = cgiGetSize("PRINTER_NAME");
+ attr = ippAddStrings(request, IPP_TAG_PRINTER, IPP_TAG_NAME,
+ type, num_users, NULL, NULL);
- for (i = 0; i < printer_count; i ++)
+ for (i = 0, ptr = (char *)users; *ptr; i ++)
{
- for (j = 0; j < export_count; j ++)
- if (!strcasecmp(cgiGetArray("PRINTER_NAME", i),
- cgiGetArray("EXPORT_NAME", j)))
- break;
-
- cgiSetArray("PRINTER_EXPORT", i, j < export_count ? "Y" : "");
- }
- }
- }
-
- /*
- * Show form...
- */
-
- cgiCopyTemplateLang("samba-export.tmpl");
- cgiEndHTML();
-}
+ /*
+ * Skip whitespace and commas...
+ */
+ while (*ptr == ',' || isspace(*ptr & 255))
+ ptr ++;
-/*
- * 'do_menu()' - Show the main menu...
- */
+ if (!*ptr)
+ break;
-static void
-do_menu(http_t *http) /* I - HTTP connection */
-{
- cups_file_t *cupsd; /* cupsd.conf file */
- char line[1024], /* Line from cupsd.conf file */
- *value; /* Value on line */
- const char *server_root; /* Location of config files */
- const char *datadir; /* Location of data files */
- ipp_t *request, /* IPP request */
- *response; /* IPP response */
- ipp_attribute_t *attr; /* IPP attribute */
+ if (*ptr == '\'' || *ptr == '\"')
+ {
+ /*
+ * Scan quoted name...
+ */
+ quote = *ptr++;
- /*
- * Locate the cupsd.conf file...
- */
+ for (end = ptr; *end; end ++)
+ if (*end == quote)
+ break;
+ }
+ else
+ {
+ /*
+ * Scan space or comma-delimited name...
+ */
- if ((server_root = getenv("CUPS_SERVERROOT")) == NULL)
- server_root = CUPS_SERVERROOT;
+ for (end = ptr; *end; end ++)
+ if (isspace(*end & 255) || *end == ',')
+ break;
+ }
- snprintf(line, sizeof(line), "%s/cupsd.conf", server_root);
+ /*
+ * Terminate the name...
+ */
- cgiStartHTML(cgiText(_("Administration")));
+ if (*end)
+ *end++ = '\0';
- printf("<!-- \"%s\" -->\n", line);
+ /*
+ * Add the name...
+ */
- /*
- * Open the cupsd.conf file...
- */
+ ippSetString(request, &attr, i, ptr);
- if ((cupsd = cupsFileOpen(line, "r")) == NULL)
- {
- /*
- * Unable to open - log an error...
- */
+ /*
+ * Advance to the next name...
+ */
- cgiSetVariable("MESSAGE", cgiText(_("Unable to open cupsd.conf file:")));
- cgiSetVariable("ERROR", strerror(errno));
- cgiCopyTemplateLang("error.tmpl");
- cgiEndHTML();
+ ptr = end;
+ }
+ }
- perror(line);
- }
- else
- {
/*
- * Read the file, keeping track of what settings are enabled...
+ * Do the request and get back a response...
*/
- int remote_access = 0, /* Remote access allowed? */
- remote_admin = 0, /* Remote administration allowed? */
- browsing = 1, /* Browsing enabled? */
- browse_allow = 1, /* Browse address set? */
- browse_address = 0, /* Browse address set? */
- cancel_policy = 1, /* Cancel-job policy set? */
- debug_logging = 0; /* LogLevel debug set? */
- int linenum = 0, /* Line number in file */
- in_policy = 0, /* In a policy section? */
- in_cancel_job = 0, /* In a cancel-job section? */
- in_admin_location = 0; /* In the /admin location? */
+ ippDelete(cupsDoRequest(http, request, "/admin/"));
-
- while (cupsFileGetConf(cupsd, line, sizeof(line), &value, &linenum))
+ if (cupsLastError() == IPP_NOT_AUTHORIZED)
{
- if (!strcasecmp(line, "Port"))
- {
- remote_access = 1;
- }
- else if (!strcasecmp(line, "Listen"))
- {
- char *port; /* Pointer to port number, if any */
-
-
- if ((port = strrchr(value, ':')) != NULL)
- *port = '\0';
-
- if (strcasecmp(value, "localhost") && strcmp(value, "127.0.0.1"))
- remote_access = 1;
- }
- else if (!strcasecmp(line, "Browsing"))
- {
- browsing = !strcasecmp(value, "yes") || !strcasecmp(value, "on") ||
- !strcasecmp(value, "true");
- }
- else if (!strcasecmp(line, "BrowseAddress"))
- {
- browse_address = 1;
- }
- else if (!strcasecmp(line, "BrowseAllow"))
- {
- browse_allow = 1;
- }
- else if (!strcasecmp(line, "BrowseOrder"))
- {
- browse_allow = !strncasecmp(value, "deny,", 5);
- }
- else if (!strcasecmp(line, "LogLevel"))
- {
- debug_logging = !strncasecmp(value, "debug", 5);
- }
- else if (!strcasecmp(line, "<Policy") && !strcasecmp(value, "default"))
- {
- in_policy = 1;
- }
- else if (!strcasecmp(line, "</Policy>"))
- {
- in_policy = 0;
- }
- else if (!strcasecmp(line, "<Limit") && in_policy)
- {
- /*
- * See if the policy limit is for the Cancel-Job operation...
- */
-
- char *valptr; /* Pointer into value */
-
-
- while (*value)
- {
- for (valptr = value; !isspace(*valptr & 255) && *valptr; valptr ++);
-
- if (*valptr)
- *valptr++ = '\0';
-
- if (!strcasecmp(value, "cancel-job") || !strcasecmp(value, "all"))
- {
- in_cancel_job = 1;
- break;
- }
-
- for (value = valptr; isspace(*value & 255); value ++);
- }
- }
- else if (!strcasecmp(line, "</Limit>"))
- {
- in_cancel_job = 0;
- }
- else if (!strcasecmp(line, "Require") && in_cancel_job)
- {
- cancel_policy = 0;
- }
- else if (!strcasecmp(line, "<Location") && !strcasecmp(value, "/admin"))
- {
- in_admin_location = 1;
- }
- else if (!strcasecmp(line, "</Location>"))
- {
- in_admin_location = 0;
- }
- else if (!strcasecmp(line, "Allow") && in_admin_location &&
- strcasecmp(value, "localhost") && strcasecmp(value, "127.0.0.1"))
- {
- remote_admin = 1;
- }
+ puts("Status: 401\n");
+ exit(0);
}
-
- cupsFileClose(cupsd);
-
- if (browsing && browse_allow)
- cgiSetVariable("REMOTE_PRINTERS", "CHECKED");
-
- if (remote_access && browsing && browse_address)
- cgiSetVariable("SHARE_PRINTERS", "CHECKED");
-
- if (remote_access && remote_admin)
- cgiSetVariable("REMOTE_ADMIN", "CHECKED");
-
- if (cancel_policy)
- cgiSetVariable("USER_CANCEL_ANY", "CHECKED");
-
- if (debug_logging)
- cgiSetVariable("DEBUG_LOGGING", "CHECKED");
- }
-
- /*
- * Get the list of printers and their devices...
- */
-
- request = ippNewRequest(CUPS_GET_PRINTERS);
-
- ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
- "requested-attributes", NULL, "device-uri");
-
- ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_ENUM, "printer-type",
- CUPS_PRINTER_LOCAL);
- ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_ENUM, "printer-type-mask",
- CUPS_PRINTER_LOCAL);
-
- if ((response = cupsDoRequest(http, request, "/")) != NULL)
- {
- /*
- * Got the printer list, now load the devices...
- */
-
- int i; /* Looping var */
- cups_array_t *printer_devices; /* Printer devices for local printers */
- char *printer_device; /* Current printer device */
-
-
- /*
- * Allocate an array and copy the device strings...
- */
-
- printer_devices = cupsArrayNew((cups_array_func_t)strcmp, NULL);
-
- for (attr = ippFindAttribute(response, "device-uri", IPP_TAG_URI);
- attr;
- attr = ippFindNextAttribute(response, "device-uri", IPP_TAG_URI))
+ else if (cupsLastError() > IPP_OK_CONFLICT)
{
- cupsArrayAdd(printer_devices, strdup(attr->values[0].string.text));
+ cgiStartHTML(cgiText(_("Set Allowed Users")));
+ cgiShowIPPError(_("Unable to change printer"));
}
-
- /*
- * Free the printer list and get the device list...
- */
-
- ippDelete(response);
-
- request = ippNewRequest(CUPS_GET_DEVICES);
-
- if ((response = cupsDoRequest(http, request, "/")) != NULL)
+ else
{
/*
- * Got the device list, let's parse it...
+ * Redirect successful updates back to the printer page...
*/
- const char *device_uri, /* device-uri attribute value */
- *device_make_and_model, /* device-make-and-model value */
- *device_info; /* device-info value */
-
-
- for (i = 0, attr = response->attrs; attr; attr = attr->next)
- {
- /*
- * Skip leading attributes until we hit a device...
- */
-
- while (attr && attr->group_tag != IPP_TAG_PRINTER)
- attr = attr->next;
-
- if (!attr)
- break;
-
- /*
- * Pull the needed attributes from this device...
- */
-
- device_info = NULL;
- device_make_and_model = NULL;
- device_uri = NULL;
-
- while (attr && attr->group_tag == IPP_TAG_PRINTER)
- {
- if (!strcmp(attr->name, "device-info") &&
- attr->value_tag == IPP_TAG_TEXT)
- device_info = attr->values[0].string.text;
-
- if (!strcmp(attr->name, "device-make-and-model") &&
- attr->value_tag == IPP_TAG_TEXT)
- device_make_and_model = attr->values[0].string.text;
-
- if (!strcmp(attr->name, "device-uri") &&
- attr->value_tag == IPP_TAG_URI)
- device_uri = attr->values[0].string.text;
-
- attr = attr->next;
- }
-
- /*
- * See if we have everything needed...
- */
-
- if (device_info && device_make_and_model && device_uri &&
- strcasecmp(device_make_and_model, "unknown") &&
- strchr(device_uri, ':'))
- {
- /*
- * Yes, now see if there is already a printer for this
- * device...
- */
-
- if (!cupsArrayFind(printer_devices, (void *)device_uri))
- {
- /*
- * Not found, so it must be a new printer...
- */
-
- char options[1024], /* Form variables for this device */
- *options_ptr; /* Pointer into string */
- const char *ptr; /* Pointer into device string */
-
-
- /*
- * Format the printer name variable for this device...
- *
- * We use the device-info string first, then device-uri,
- * and finally device-make-and-model to come up with a
- * suitable name.
- */
-
- strcpy(options, "PRINTER_NAME=");
- options_ptr = options + strlen(options);
-
- if (strncasecmp(device_info, "unknown", 7))
- ptr = device_info;
- else if ((ptr = strstr(device_uri, "://")) != NULL)
- ptr += 3;
- else
- ptr = device_make_and_model;
-
- for (;
- options_ptr < (options + sizeof(options) - 1) && *ptr;
- ptr ++)
- if (isalnum(*ptr & 255) || *ptr == '_' || *ptr == '-' || *ptr == '.')
- *options_ptr++ = *ptr;
- else if ((*ptr == ' ' || *ptr == '/') && options_ptr[-1] != '_')
- *options_ptr++ = '_';
- else if (*ptr == '?' || *ptr == '(')
- break;
-
- /*
- * Then add the make and model in the printer info, so
- * that MacOS clients see something reasonable...
- */
-
- strlcpy(options_ptr, "&PRINTER_LOCATION=Local+Printer"
- "&PRINTER_INFO=",
- sizeof(options) - (options_ptr - options));
- options_ptr += strlen(options_ptr);
-
- cgiFormEncode(options_ptr, device_make_and_model,
- sizeof(options) - (options_ptr - options));
- options_ptr += strlen(options_ptr);
-
- /*
- * Then copy the device URI...
- */
-
- strlcpy(options_ptr, "&DEVICE_URI=",
- sizeof(options) - (options_ptr - options));
- options_ptr += strlen(options_ptr);
-
- cgiFormEncode(options_ptr, device_uri,
- sizeof(options) - (options_ptr - options));
- options_ptr += strlen(options_ptr);
-
- if (options_ptr < (options + sizeof(options) - 1))
- {
- *options_ptr++ = '|';
- cgiFormEncode(options_ptr, device_make_and_model,
- sizeof(options) - (options_ptr - options));
- }
-
- /*
- * Finally, set the form variables for this printer...
- */
-
- cgiSetArray("device_info", i, device_info);
- cgiSetArray("device_make_and_model", i, device_make_and_model);
- cgiSetArray("device_options", i, options);
- cgiSetArray("device_uri", i, device_uri);
- i ++;
- }
- }
-
- if (!attr)
- break;
- }
+ char url[1024], /* Printer/class URL */
+ refresh[1024]; /* Refresh URL */
- ippDelete(response);
- /*
- * Free the device list...
- */
+ cgiRewriteURL(uri, url, sizeof(url), NULL);
+ cgiFormEncode(uri, url, sizeof(uri));
+ snprintf(refresh, sizeof(refresh), "5;URL=/admin/?OP=redirect&URL=%s",
+ uri);
+ cgiSetVariable("refresh_page", refresh);
- for (printer_device = (char *)cupsArrayFirst(printer_devices);
- printer_device;
- printer_device = (char *)cupsArrayNext(printer_devices))
- free(printer_device);
+ cgiStartHTML(cgiText(_("Set Allowed Users")));
- cupsArrayDelete(printer_devices);
+ cgiCopyTemplateLang(is_class ? "class-modified.tmpl" :
+ "printer-modified.tmpl");
}
- }
-
- /*
- * See if Samba and the Windows drivers are installed...
- */
-
- if ((datadir = getenv("CUPS_DATADIR")) == NULL)
- datadir = CUPS_DATADIR;
-
- snprintf(line, sizeof(line), "%s/drivers/pscript5.dll", datadir);
- if (!access(line, 0))
- {
- /*
- * Found Windows 2000 driver file, see if we have smbclient and
- * rpcclient...
- */
-
- if (cupsFileFind("smbclient", getenv("PATH"), line, sizeof(line)) &&
- cupsFileFind("rpcclient", getenv("PATH"), line, sizeof(line)))
- cgiSetVariable("HAVE_SAMBA", "Y");
- else
- {
- if (!cupsFileFind("smbclient", getenv("PATH"), line, sizeof(line)))
- fputs("ERROR: smbclient not found!\n", stderr);
- if (!cupsFileFind("rpcclient", getenv("PATH"), line, sizeof(line)))
- fputs("ERROR: rpcclient not found!\n", stderr);
- }
+ cgiEndHTML();
}
- else
- perror(line);
-
- /*
- * Finally, show the main menu template...
- */
-
- cgiCopyTemplateLang("admin.tmpl");
-
- cgiEndHTML();
}
/*
- * 'do_printer_op()' - Do a printer operation.
+ * 'do_set_default()' - Set the server default printer/class.
*/
static void
-do_printer_op(http_t *http, /* I - HTTP connection */
- ipp_op_t op, /* I - Operation to perform */
- const char *title) /* I - Title of page */
+do_set_default(http_t *http) /* I - HTTP connection */
{
+ const char *title; /* Page title */
ipp_t *request; /* IPP request */
char uri[HTTP_MAX_URI]; /* Printer URI */
const char *printer, /* Printer name (purge-jobs) */
is_class = cgiGetVariable("IS_CLASS");
printer = cgiGetVariable("PRINTER_NAME");
+ title = cgiText(_("Set As Server Default"));
if (!printer)
{
- cgiSetVariable("ERROR", cgiText(_("Missing form variable!")));
+ cgiSetVariable("ERROR", cgiText(_("Missing form variable")));
cgiStartHTML(title);
cgiCopyTemplateLang("error.tmpl");
cgiEndHTML();
* printer-uri
*/
- request = ippNewRequest(op);
+ request = ippNewRequest(CUPS_SET_DEFAULT);
- httpAssembleURIf(uri, sizeof(uri), "ipp", NULL, "localhost", 0,
- is_class ? "/classes/%s" : "/printers/%s", printer);
+ httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
+ "localhost", 0, is_class ? "/classes/%s" : "/printers/%s",
+ printer);
ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
NULL, uri);
ippDelete(cupsDoRequest(http, request, "/admin/"));
- if (cupsLastError() > IPP_OK_CONFLICT)
+ if (cupsLastError() == IPP_NOT_AUTHORIZED)
+ {
+ puts("Status: 401\n");
+ exit(0);
+ }
+ else if (cupsLastError() > IPP_OK_CONFLICT)
{
cgiStartHTML(title);
- cgiShowIPPError(_("Unable to change printer:"));
+ cgiShowIPPError(_("Unable to set server default"));
}
else
{
cgiRewriteURL(uri, url, sizeof(url), NULL);
cgiFormEncode(uri, url, sizeof(uri));
- snprintf(refresh, sizeof(refresh), "5;/admin/?OP=redirect&URL=%s", uri);
+ snprintf(refresh, sizeof(refresh), "5;URL=/admin/?OP=redirect&URL=%s", uri);
cgiSetVariable("refresh_page", refresh);
cgiStartHTML(title);
-
- if (op == IPP_PAUSE_PRINTER)
- cgiCopyTemplateLang("printer-stop.tmpl");
- else if (op == IPP_RESUME_PRINTER)
- cgiCopyTemplateLang("printer-start.tmpl");
- else if (op == CUPS_ACCEPT_JOBS)
- cgiCopyTemplateLang("printer-accept.tmpl");
- else if (op == CUPS_REJECT_JOBS)
- cgiCopyTemplateLang("printer-reject.tmpl");
- else if (op == IPP_PURGE_JOBS)
- cgiCopyTemplateLang("printer-purge.tmpl");
- else if (op == CUPS_SET_DEFAULT)
- cgiCopyTemplateLang("printer-default.tmpl");
+ cgiCopyTemplateLang("printer-default.tmpl");
}
cgiEndHTML();
/*
- * 'do_set_allowed_users()' - Set the allowed/denied users for a queue.
+ * 'do_set_options()' - Configure the default options for a queue.
*/
static void
-do_set_allowed_users(http_t *http) /* I - HTTP connection */
+do_set_options(http_t *http, /* I - HTTP connection */
+ int is_class) /* I - Set options for class? */
{
- int i; /* Looping var */
+ int i, j, k, m; /* Looping vars */
+ int have_options; /* Have options? */
ipp_t *request, /* IPP request */
*response; /* IPP response */
- char uri[HTTP_MAX_URI]; /* Printer URI */
- const char *printer, /* Printer name (purge-jobs) */
- *is_class, /* Is a class? */
- *users, /* List of users or groups */
- *type; /* Allow/deny type */
- int num_users; /* Number of users */
- char *ptr, /* Pointer into users string */
- *end, /* Pointer to end of users string */
- quote; /* Quote character */
- ipp_attribute_t *attr; /* Attribute */
- static const char * const attrs[] = /* Requested attributes */
- {
- "requesting-user-name-allowed",
- "requesting-user-name-denied"
- };
+ ipp_attribute_t *attr; /* IPP attribute */
+ char uri[HTTP_MAX_URI]; /* Job URI */
+ const char *var; /* Variable value */
+ const char *printer; /* Printer printer name */
+ const char *filename; /* PPD filename */
+ char tempfile[1024]; /* Temporary filename */
+ cups_file_t *in, /* Input file */
+ *out; /* Output file */
+ char line[1024], /* Line from PPD file */
+ value[1024], /* Option value */
+ keyword[1024], /* Keyword from Default line */
+ *keyptr; /* Pointer into keyword... */
+ ppd_file_t *ppd; /* PPD file */
+ ppd_group_t *group; /* Option group */
+ ppd_option_t *option; /* Option */
+ ppd_coption_t *coption; /* Custom option */
+ ppd_cparam_t *cparam; /* Custom parameter */
+ ppd_attr_t *ppdattr; /* PPD attribute */
+ const char *title; /* Page title */
- is_class = cgiGetVariable("IS_CLASS");
- printer = cgiGetVariable("PRINTER_NAME");
+ title = cgiText(is_class ? _("Set Class Options") : _("Set Printer Options"));
- if (!printer)
+ fprintf(stderr, "DEBUG: do_set_options(http=%p, is_class=%d)\n", http,
+ is_class);
+
+ /*
+ * Get the printer name...
+ */
+
+ if ((printer = cgiGetVariable("PRINTER_NAME")) != NULL)
+ httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
+ "localhost", 0, is_class ? "/classes/%s" : "/printers/%s",
+ printer);
+ else
{
- cgiSetVariable("ERROR", cgiText(_("Missing form variable!")));
- cgiStartHTML(cgiText(_("Set Allowed Users")));
+ cgiSetVariable("ERROR", cgiText(_("Missing form variable")));
+ cgiStartHTML(title);
cgiCopyTemplateLang("error.tmpl");
cgiEndHTML();
return;
}
- users = cgiGetVariable("users");
- type = cgiGetVariable("type");
+ fprintf(stderr, "DEBUG: printer=\"%s\", uri=\"%s\"...\n", printer, uri);
- if (!users || !type ||
- (strcmp(type, "requesting-user-name-allowed") &&
- strcmp(type, "requesting-user-name-denied")))
+ /*
+ * If the user clicks on the Auto-Configure button, send an AutoConfigure
+ * command file to the printer...
+ */
+
+ if (cgiGetVariable("AUTOCONFIGURE"))
+ {
+ cgiPrintCommand(http, printer, "AutoConfigure", "Set Default Options");
+ return;
+ }
+
+ /*
+ * Get the PPD file...
+ */
+
+ if (is_class)
+ filename = NULL;
+ else
+ filename = cupsGetPPD2(http, printer);
+
+ if (filename)
+ {
+ fprintf(stderr, "DEBUG: Got PPD file: \"%s\"\n", filename);
+
+ if ((ppd = ppdOpenFile(filename)) == NULL)
+ {
+ cgiSetVariable("ERROR", ppdErrorString(ppdLastError(&i)));
+ cgiSetVariable("MESSAGE", cgiText(_("Unable to open PPD file")));
+ cgiStartHTML(title);
+ cgiCopyTemplateLang("error.tmpl");
+ cgiEndHTML();
+ return;
+ }
+ }
+ else
+ {
+ fputs("DEBUG: No PPD file\n", stderr);
+ ppd = NULL;
+ }
+
+ if (cgiGetVariable("job_sheets_start") != NULL ||
+ cgiGetVariable("job_sheets_end") != NULL)
+ have_options = 1;
+ else
+ have_options = 0;
+
+ if (ppd)
+ {
+ ppdMarkDefaults(ppd);
+
+ for (option = ppdFirstOption(ppd);
+ option;
+ option = ppdNextOption(ppd))
+ {
+ if ((var = cgiGetVariable(option->keyword)) != NULL)
+ {
+ have_options = 1;
+ ppdMarkOption(ppd, option->keyword, var);
+ fprintf(stderr, "DEBUG: Set %s to %s...\n", option->keyword, var);
+ }
+ else
+ fprintf(stderr, "DEBUG: Didn't find %s...\n", option->keyword);
+ }
+ }
+
+ if (!have_options || ppdConflicts(ppd))
{
/*
- * Build a Get-Printer-Attributes request, which requires the following
- * attributes:
- *
- * attributes-charset
- * attributes-natural-language
- * printer-uri
- * requested-attributes
+ * Show the options to the user...
+ */
+
+ fputs("DEBUG: Showing options...\n", stderr);
+
+ /*
+ * Show auto-configure button if supported...
+ */
+
+ if (ppd)
+ {
+ if (ppd->num_filters == 0 ||
+ ((ppdattr = ppdFindAttr(ppd, "cupsCommands", NULL)) != NULL &&
+ ppdattr->value && strstr(ppdattr->value, "AutoConfigure")))
+ cgiSetVariable("HAVE_AUTOCONFIGURE", "YES");
+ else
+ {
+ for (i = 0; i < ppd->num_filters; i ++)
+ if (!strncmp(ppd->filters[i], "application/vnd.cups-postscript", 31))
+ {
+ cgiSetVariable("HAVE_AUTOCONFIGURE", "YES");
+ break;
+ }
+ }
+ }
+
+ /*
+ * Get the printer attributes...
*/
request = ippNewRequest(IPP_GET_PRINTER_ATTRIBUTES);
- httpAssembleURIf(uri, sizeof(uri), "ipp", NULL, "localhost", 0,
- is_class ? "/classes/%s" : "/printers/%s", printer);
+ httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
+ "localhost", 0, "/printers/%s", printer);
ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
- NULL, uri);
+ NULL, uri);
- ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
- "requested-attributes",
- (int)(sizeof(attrs) / sizeof(attrs[0])), NULL, attrs);
+ response = cupsDoRequest(http, request, "/");
/*
- * Do the request and get back a response...
+ * List the groups used as "tabs"...
*/
- if ((response = cupsDoRequest(http, request, "/")) != NULL)
+ i = 0;
+
+ if (ppd)
{
- cgiSetIPPVars(response, NULL, NULL, NULL, 0);
+ for (group = ppd->groups;
+ i < ppd->num_groups;
+ i ++, group ++)
+ {
+ cgiSetArray("GROUP_ID", i, group->name);
- ippDelete(response);
+ if (!strcmp(group->name, "InstallableOptions"))
+ cgiSetArray("GROUP", i, cgiText(_("Options Installed")));
+ else
+ cgiSetArray("GROUP", i, group->text);
+ }
}
- cgiStartHTML(cgiText(_("Set Allowed Users")));
+ if (ippFindAttribute(response, "job-sheets-supported", IPP_TAG_ZERO))
+ {
+ cgiSetArray("GROUP_ID", i, "CUPS_BANNERS");
+ cgiSetArray("GROUP", i ++, cgiText(_("Banners")));
+ }
- if (cupsLastError() > IPP_OK_CONFLICT)
- cgiShowIPPError(_("Unable to get printer attributes:"));
- else
- cgiCopyTemplateLang("users.tmpl");
+ if (ippFindAttribute(response, "printer-error-policy-supported",
+ IPP_TAG_ZERO) ||
+ ippFindAttribute(response, "printer-op-policy-supported",
+ IPP_TAG_ZERO))
+ {
+ cgiSetArray("GROUP_ID", i, "CUPS_POLICIES");
+ cgiSetArray("GROUP", i ++, cgiText(_("Policies")));
+ }
- cgiEndHTML();
- }
- else
- {
- /*
- * Save the changes...
- */
+ if ((attr = ippFindAttribute(response, "port-monitor-supported",
+ IPP_TAG_NAME)) != NULL && attr->num_values > 1)
+ {
+ cgiSetArray("GROUP_ID", i, "CUPS_PORT_MONITOR");
+ cgiSetArray("GROUP", i, cgiText(_("Port Monitor")));
+ }
- for (num_users = 0, ptr = (char *)users; *ptr; num_users ++)
+ cgiStartHTML(cgiText(_("Set Printer Options")));
+ cgiCopyTemplateLang("set-printer-options-header.tmpl");
+
+ if (ppd)
+ {
+ ppdLocalize(ppd);
+
+ if (ppdConflicts(ppd))
+ {
+ for (i = ppd->num_groups, k = 0, group = ppd->groups;
+ i > 0;
+ i --, group ++)
+ for (j = group->num_options, option = group->options;
+ j > 0;
+ j --, option ++)
+ if (option->conflicted)
+ {
+ cgiSetArray("ckeyword", k, option->keyword);
+ cgiSetArray("ckeytext", k, option->text);
+
+ for (m = 0; m < option->num_choices; m ++)
+ {
+ if (option->choices[m].marked)
+ {
+ cgiSetArray("cchoice", k, option->choices[m].text);
+ break;
+ }
+ }
+
+ k ++;
+ }
+
+ cgiCopyTemplateLang("option-conflict.tmpl");
+ }
+
+ for (i = ppd->num_groups, group = ppd->groups;
+ i > 0;
+ i --, group ++)
+ {
+ for (j = group->num_options, option = group->options;
+ j > 0;
+ j --, option ++)
+ {
+ if (!strcmp(option->keyword, "PageRegion"))
+ continue;
+
+ if (option->num_choices > 1)
+ break;
+ }
+
+ if (j == 0)
+ continue;
+
+ cgiSetVariable("GROUP_ID", group->name);
+
+ if (!strcmp(group->name, "InstallableOptions"))
+ cgiSetVariable("GROUP", cgiText(_("Options Installed")));
+ else
+ cgiSetVariable("GROUP", group->text);
+
+ cgiCopyTemplateLang("option-header.tmpl");
+
+ for (j = group->num_options, option = group->options;
+ j > 0;
+ j --, option ++)
+ {
+ if (!strcmp(option->keyword, "PageRegion") || option->num_choices < 2)
+ continue;
+
+ cgiSetVariable("KEYWORD", option->keyword);
+ cgiSetVariable("KEYTEXT", option->text);
+
+ if (option->conflicted)
+ cgiSetVariable("CONFLICTED", "1");
+ else
+ cgiSetVariable("CONFLICTED", "0");
+
+ cgiSetSize("CHOICES", 0);
+ cgiSetSize("TEXT", 0);
+ for (k = 0, m = 0; k < option->num_choices; k ++)
+ {
+ cgiSetArray("CHOICES", m, option->choices[k].choice);
+ cgiSetArray("TEXT", m, option->choices[k].text);
+
+ m ++;
+
+ if (option->choices[k].marked)
+ cgiSetVariable("DEFCHOICE", option->choices[k].choice);
+ }
+
+ cgiSetSize("PARAMS", 0);
+ cgiSetSize("PARAMTEXT", 0);
+ cgiSetSize("PARAMVALUE", 0);
+ cgiSetSize("INPUTTYPE", 0);
+
+ if ((coption = ppdFindCustomOption(ppd, option->keyword)))
+ {
+ const char *units = NULL; /* Units value, if any */
+
+ cgiSetVariable("ISCUSTOM", "1");
+
+ for (cparam = ppdFirstCustomParam(coption), m = 0;
+ cparam;
+ cparam = ppdNextCustomParam(coption), m ++)
+ {
+ if (!_cups_strcasecmp(option->keyword, "PageSize") &&
+ _cups_strcasecmp(cparam->name, "Width") &&
+ _cups_strcasecmp(cparam->name, "Height"))
+ {
+ m --;
+ continue;
+ }
+
+ cgiSetArray("PARAMS", m, cparam->name);
+ cgiSetArray("PARAMTEXT", m, cparam->text);
+ cgiSetArray("INPUTTYPE", m, "text");
+
+ switch (cparam->type)
+ {
+ case PPD_CUSTOM_UNKNOWN :
+ break;
+
+ case PPD_CUSTOM_POINTS :
+ if (!_cups_strncasecmp(option->defchoice, "Custom.", 7))
+ {
+ units = option->defchoice + strlen(option->defchoice) - 2;
+
+ if (strcmp(units, "mm") && strcmp(units, "cm") &&
+ strcmp(units, "in") && strcmp(units, "ft"))
+ {
+ if (units[1] == 'm')
+ units ++;
+ else
+ units = "pt";
+ }
+ }
+ else
+ units = "pt";
+
+ if (!strcmp(units, "mm"))
+ snprintf(value, sizeof(value), "%g",
+ cparam->current.custom_points / 72.0 * 25.4);
+ else if (!strcmp(units, "cm"))
+ snprintf(value, sizeof(value), "%g",
+ cparam->current.custom_points / 72.0 * 2.54);
+ else if (!strcmp(units, "in"))
+ snprintf(value, sizeof(value), "%g",
+ cparam->current.custom_points / 72.0);
+ else if (!strcmp(units, "ft"))
+ snprintf(value, sizeof(value), "%g",
+ cparam->current.custom_points / 72.0 / 12.0);
+ else if (!strcmp(units, "m"))
+ snprintf(value, sizeof(value), "%g",
+ cparam->current.custom_points / 72.0 * 0.0254);
+ else
+ snprintf(value, sizeof(value), "%g",
+ cparam->current.custom_points);
+ cgiSetArray("PARAMVALUE", m, value);
+ break;
+
+ case PPD_CUSTOM_CURVE :
+ case PPD_CUSTOM_INVCURVE :
+ case PPD_CUSTOM_REAL :
+ snprintf(value, sizeof(value), "%g",
+ cparam->current.custom_real);
+ cgiSetArray("PARAMVALUE", m, value);
+ break;
+
+ case PPD_CUSTOM_INT:
+ snprintf(value, sizeof(value), "%d",
+ cparam->current.custom_int);
+ cgiSetArray("PARAMVALUE", m, value);
+ break;
+
+ case PPD_CUSTOM_PASSCODE:
+ case PPD_CUSTOM_PASSWORD:
+ if (cparam->current.custom_password)
+ cgiSetArray("PARAMVALUE", m,
+ cparam->current.custom_password);
+ else
+ cgiSetArray("PARAMVALUE", m, "");
+ cgiSetArray("INPUTTYPE", m, "password");
+ break;
+
+ case PPD_CUSTOM_STRING:
+ if (cparam->current.custom_string)
+ cgiSetArray("PARAMVALUE", m,
+ cparam->current.custom_string);
+ else
+ cgiSetArray("PARAMVALUE", m, "");
+ break;
+ }
+ }
+
+ if (units)
+ {
+ cgiSetArray("PARAMS", m, "Units");
+ cgiSetArray("PARAMTEXT", m, cgiText(_("Units")));
+ cgiSetArray("PARAMVALUE", m, units);
+ }
+ }
+ else
+ cgiSetVariable("ISCUSTOM", "0");
+
+ switch (option->ui)
+ {
+ case PPD_UI_BOOLEAN :
+ cgiCopyTemplateLang("option-boolean.tmpl");
+ break;
+ case PPD_UI_PICKONE :
+ cgiCopyTemplateLang("option-pickone.tmpl");
+ break;
+ case PPD_UI_PICKMANY :
+ cgiCopyTemplateLang("option-pickmany.tmpl");
+ break;
+ }
+ }
+
+ cgiCopyTemplateLang("option-trailer.tmpl");
+ }
+ }
+
+ if ((attr = ippFindAttribute(response, "job-sheets-supported",
+ IPP_TAG_ZERO)) != NULL)
{
/*
- * Skip whitespace and commas...
+ * Add the job sheets options...
*/
- while (*ptr == ',' || isspace(*ptr & 255))
- ptr ++;
+ cgiSetVariable("GROUP_ID", "CUPS_BANNERS");
+ cgiSetVariable("GROUP", cgiText(_("Banners")));
+ cgiCopyTemplateLang("option-header.tmpl");
- if (*ptr == '\'' || *ptr == '\"')
+ cgiSetSize("CHOICES", attr->num_values);
+ cgiSetSize("TEXT", attr->num_values);
+ for (k = 0; k < attr->num_values; k ++)
{
- /*
- * Scan quoted name...
- */
+ cgiSetArray("CHOICES", k, attr->values[k].string.text);
+ cgiSetArray("TEXT", k, attr->values[k].string.text);
+ }
- quote = *ptr++;
+ attr = ippFindAttribute(response, "job-sheets-default", IPP_TAG_ZERO);
+
+ cgiSetVariable("KEYWORD", "job_sheets_start");
+ cgiSetVariable("KEYTEXT",
+ /* TRANSLATORS: Banner/cover sheet before the print job. */
+ cgiText(_("Starting Banner")));
+ cgiSetVariable("DEFCHOICE", attr != NULL ?
+ attr->values[0].string.text : "");
+
+ cgiCopyTemplateLang("option-pickone.tmpl");
+
+ cgiSetVariable("KEYWORD", "job_sheets_end");
+ cgiSetVariable("KEYTEXT",
+ /* TRANSLATORS: Banner/cover sheet after the print job. */
+ cgiText(_("Ending Banner")));
+ cgiSetVariable("DEFCHOICE", attr != NULL && attr->num_values > 1 ?
+ attr->values[1].string.text : "");
+
+ cgiCopyTemplateLang("option-pickone.tmpl");
+
+ cgiCopyTemplateLang("option-trailer.tmpl");
+ }
+
+ if (ippFindAttribute(response, "printer-error-policy-supported",
+ IPP_TAG_ZERO) ||
+ ippFindAttribute(response, "printer-op-policy-supported",
+ IPP_TAG_ZERO))
+ {
+ /*
+ * Add the error and operation policy options...
+ */
+
+ cgiSetVariable("GROUP_ID", "CUPS_POLICIES");
+ cgiSetVariable("GROUP", cgiText(_("Policies")));
+ cgiCopyTemplateLang("option-header.tmpl");
+
+ /*
+ * Error policy...
+ */
+
+ attr = ippFindAttribute(response, "printer-error-policy-supported",
+ IPP_TAG_ZERO);
+
+ if (attr)
+ {
+ cgiSetSize("CHOICES", attr->num_values);
+ cgiSetSize("TEXT", attr->num_values);
+ for (k = 0; k < attr->num_values; k ++)
+ {
+ cgiSetArray("CHOICES", k, attr->values[k].string.text);
+ cgiSetArray("TEXT", k, attr->values[k].string.text);
+ }
+
+ attr = ippFindAttribute(response, "printer-error-policy",
+ IPP_TAG_ZERO);
+
+ cgiSetVariable("KEYWORD", "printer_error_policy");
+ cgiSetVariable("KEYTEXT", cgiText(_("Error Policy")));
+ cgiSetVariable("DEFCHOICE", attr == NULL ?
+ "" : attr->values[0].string.text);
+ }
+
+ cgiCopyTemplateLang("option-pickone.tmpl");
+
+ /*
+ * Operation policy...
+ */
+
+ attr = ippFindAttribute(response, "printer-op-policy-supported",
+ IPP_TAG_ZERO);
+
+ if (attr)
+ {
+ cgiSetSize("CHOICES", attr->num_values);
+ cgiSetSize("TEXT", attr->num_values);
+ for (k = 0; k < attr->num_values; k ++)
+ {
+ cgiSetArray("CHOICES", k, attr->values[k].string.text);
+ cgiSetArray("TEXT", k, attr->values[k].string.text);
+ }
+
+ attr = ippFindAttribute(response, "printer-op-policy", IPP_TAG_ZERO);
+
+ cgiSetVariable("KEYWORD", "printer_op_policy");
+ cgiSetVariable("KEYTEXT", cgiText(_("Operation Policy")));
+ cgiSetVariable("DEFCHOICE", attr == NULL ?
+ "" : attr->values[0].string.text);
+
+ cgiCopyTemplateLang("option-pickone.tmpl");
+ }
+
+ cgiCopyTemplateLang("option-trailer.tmpl");
+ }
+
+ /*
+ * Binary protocol support...
+ */
+
+ if ((attr = ippFindAttribute(response, "port-monitor-supported",
+ IPP_TAG_NAME)) != NULL && attr->num_values > 1)
+ {
+ cgiSetVariable("GROUP_ID", "CUPS_PORT_MONITOR");
+ cgiSetVariable("GROUP", cgiText(_("Port Monitor")));
+
+ cgiSetSize("CHOICES", attr->num_values);
+ cgiSetSize("TEXT", attr->num_values);
- for (end = ptr; *end; end ++)
- if (*end == quote)
- break;
- }
- else
+ for (i = 0; i < attr->num_values; i ++)
{
- /*
- * Scan space or comma-delimited name...
- */
-
- for (end = ptr; *end; end ++)
- if (isspace(*end & 255) || *end == ',')
- break;
+ cgiSetArray("CHOICES", i, attr->values[i].string.text);
+ cgiSetArray("TEXT", i, attr->values[i].string.text);
}
- /*
- * Advance to the next name...
- */
+ attr = ippFindAttribute(response, "port-monitor", IPP_TAG_NAME);
+ cgiSetVariable("KEYWORD", "port_monitor");
+ cgiSetVariable("KEYTEXT", cgiText(_("Port Monitor")));
+ cgiSetVariable("DEFCHOICE", attr ? attr->values[0].string.text : "none");
- ptr = end;
+ cgiCopyTemplateLang("option-header.tmpl");
+ cgiCopyTemplateLang("option-pickone.tmpl");
+ cgiCopyTemplateLang("option-trailer.tmpl");
}
+ cgiCopyTemplateLang("set-printer-options-trailer.tmpl");
+ cgiEndHTML();
+
+ ippDelete(response);
+ }
+ else
+ {
/*
- * Build a CUPS-Add-Printer/Class request, which requires the following
- * attributes:
- *
- * attributes-charset
- * attributes-natural-language
- * printer-uri
- * requesting-user-name-{allowed,denied}
+ * Set default options...
*/
- request = ippNewRequest(is_class ? CUPS_ADD_CLASS : CUPS_ADD_PRINTER);
-
- httpAssembleURIf(uri, sizeof(uri), "ipp", NULL, "localhost", 0,
- is_class ? "/classes/%s" : "/printers/%s", printer);
- ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
- NULL, uri);
+ fputs("DEBUG: Setting options...\n", stderr);
- if (num_users == 0)
- ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
- "requesting-user-name-allowed", NULL, "all");
- else
+ if (filename)
{
- attr = ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
- type, num_users, NULL, NULL);
+ out = cupsTempFile2(tempfile, sizeof(tempfile));
+ in = cupsFileOpen(filename, "r");
- for (i = 0, ptr = (char *)users; *ptr; i ++)
+ if (!in || !out)
{
- /*
- * Skip whitespace and commas...
- */
+ cgiSetVariable("ERROR", strerror(errno));
+ cgiStartHTML(cgiText(_("Set Printer Options")));
+ cgiCopyTemplateLang("error.tmpl");
+ cgiEndHTML();
- while (*ptr == ',' || isspace(*ptr & 255))
- ptr ++;
+ if (in)
+ cupsFileClose(in);
- if (*ptr == '\'' || *ptr == '\"')
+ if (out)
{
- /*
- * Scan quoted name...
- */
+ cupsFileClose(out);
+ unlink(tempfile);
+ }
- quote = *ptr++;
+ unlink(filename);
+ return;
+ }
- for (end = ptr; *end; end ++)
- if (*end == quote)
- break;
- }
+ while (cupsFileGets(in, line, sizeof(line)))
+ {
+ if (!strncmp(line, "*cupsProtocol:", 14))
+ continue;
+ else if (strncmp(line, "*Default", 8))
+ cupsFilePrintf(out, "%s\n", line);
else
{
/*
- * Scan space or comma-delimited name...
+ * Get default option name...
*/
- for (end = ptr; *end; end ++)
- if (isspace(*end & 255) || *end == ',')
- break;
- }
+ strlcpy(keyword, line + 8, sizeof(keyword));
- /*
- * Terminate the name...
- */
+ for (keyptr = keyword; *keyptr; keyptr ++)
+ if (*keyptr == ':' || isspace(*keyptr & 255))
+ break;
- if (*end)
- *end++ = '\0';
+ *keyptr = '\0';
- /*
- * Add the name...
- */
+ if (!strcmp(keyword, "PageRegion") ||
+ !strcmp(keyword, "PaperDimension") ||
+ !strcmp(keyword, "ImageableArea"))
+ var = get_option_value(ppd, "PageSize", value, sizeof(value));
+ else
+ var = get_option_value(ppd, keyword, value, sizeof(value));
- attr->values[i].string.text = strdup(ptr);
+ if (!var)
+ cupsFilePrintf(out, "%s\n", line);
+ else
+ cupsFilePrintf(out, "*Default%s: %s\n", keyword, var);
+ }
+ }
- /*
- * Advance to the next name...
- */
+ cupsFileClose(in);
+ cupsFileClose(out);
+ }
+ else
+ {
+ /*
+ * Make sure temporary filename is cleared when there is no PPD...
+ */
- ptr = end;
- }
+ tempfile[0] = '\0';
}
+ /*
+ * Build a CUPS_ADD_MODIFY_CLASS/PRINTER request, which requires the
+ * following attributes:
+ *
+ * attributes-charset
+ * attributes-natural-language
+ * printer-uri
+ * job-sheets-default
+ * printer-error-policy
+ * printer-op-policy
+ * [ppd file]
+ */
+
+ request = ippNewRequest(is_class ? CUPS_ADD_MODIFY_CLASS :
+ CUPS_ADD_MODIFY_PRINTER);
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
+ NULL, uri);
+
+ attr = ippAddStrings(request, IPP_TAG_PRINTER, IPP_TAG_NAME,
+ "job-sheets-default", 2, NULL, NULL);
+ ippSetString(request, &attr, 0, cgiGetVariable("job_sheets_start"));
+ ippSetString(request, &attr, 1, cgiGetVariable("job_sheets_end"));
+
+ if ((var = cgiGetVariable("printer_error_policy")) != NULL)
+ ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_NAME,
+ "printer-error-policy", NULL, var);
+
+ if ((var = cgiGetVariable("printer_op_policy")) != NULL)
+ ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_NAME,
+ "printer-op-policy", NULL, var);
+
+ if ((var = cgiGetVariable("port_monitor")) != NULL)
+ ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_NAME,
+ "port-monitor", NULL, var);
+
/*
* Do the request and get back a response...
*/
- ippDelete(cupsDoRequest(http, request, "/admin/"));
+ if (filename)
+ ippDelete(cupsDoFileRequest(http, request, "/admin/", tempfile));
+ else
+ ippDelete(cupsDoRequest(http, request, "/admin/"));
- if (cupsLastError() > IPP_OK_CONFLICT)
+ if (cupsLastError() == IPP_NOT_AUTHORIZED)
{
- cgiStartHTML(cgiText(_("Set Allowed Users")));
- cgiShowIPPError(_("Unable to change printer:"));
+ puts("Status: 401\n");
+ exit(0);
+ }
+ else if (cupsLastError() > IPP_OK_CONFLICT)
+ {
+ cgiStartHTML(title);
+ cgiShowIPPError(_("Unable to set options"));
}
else
{
* Redirect successful updates back to the printer page...
*/
- char url[1024], /* Printer/class URL */
- refresh[1024]; /* Refresh URL */
+ char refresh[1024]; /* Refresh URL */
- cgiRewriteURL(uri, url, sizeof(url), NULL);
- cgiFormEncode(uri, url, sizeof(uri));
- snprintf(refresh, sizeof(refresh), "5;/admin/?OP=redirect&URL=%s", uri);
+ cgiFormEncode(uri, printer, sizeof(uri));
+ snprintf(refresh, sizeof(refresh), "5;URL=/admin/?OP=redirect&URL=/%s/%s",
+ is_class ? "classes" : "printers", uri);
cgiSetVariable("refresh_page", refresh);
- cgiStartHTML(cgiText(_("Set Allowed Users")));
+ cgiStartHTML(title);
- cgiCopyTemplateLang(is_class ? "class-modified.tmpl" :
- "printer-modified.tmpl");
+ cgiCopyTemplateLang("printer-configured.tmpl");
}
cgiEndHTML();
+
+ if (filename)
+ unlink(tempfile);
}
+
+ if (filename)
+ unlink(filename);
}
/*
- * 'do_set_sharing()' - Set printer-is-shared value...
+ * 'do_set_sharing()' - Set printer-is-shared value.
*/
static void
if (!printer || !shared)
{
- cgiSetVariable("ERROR", cgiText(_("Missing form variable!")));
+ cgiSetVariable("ERROR", cgiText(_("Missing form variable")));
cgiStartHTML(cgiText(_("Set Publishing")));
cgiCopyTemplateLang("error.tmpl");
cgiEndHTML();
request = ippNewRequest(is_class ? CUPS_ADD_CLASS : CUPS_ADD_PRINTER);
- httpAssembleURIf(uri, sizeof(uri), "ipp", NULL, "localhost", 0,
- is_class ? "/classes/%s" : "/printers/%s", printer);
+ httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
+ "localhost", 0, is_class ? "/classes/%s" : "/printers/%s",
+ printer);
ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
NULL, uri);
- ippAddBoolean(request, IPP_TAG_OPERATION, "printer-is-shared", atoi(shared));
+ ippAddBoolean(request, IPP_TAG_OPERATION, "printer-is-shared", (char)atoi(shared));
/*
* Do the request and get back a response...
ippDelete(response);
}
- if (cupsLastError() > IPP_OK_CONFLICT)
+ if (cupsLastError() == IPP_NOT_AUTHORIZED)
+ {
+ puts("Status: 401\n");
+ exit(0);
+ }
+ else if (cupsLastError() > IPP_OK_CONFLICT)
{
cgiStartHTML(cgiText(_("Set Publishing")));
- cgiShowIPPError(_("Unable to change printer-is-shared attribute:"));
+ cgiShowIPPError(_("Unable to change printer-is-shared attribute"));
}
else
{
cgiRewriteURL(uri, url, sizeof(url), NULL);
cgiFormEncode(uri, url, sizeof(uri));
- snprintf(refresh, sizeof(refresh), "5;/admin/?OP=redirect&URL=%s", uri);
+ snprintf(refresh, sizeof(refresh), "5;URL=/admin/?OP=redirect&URL=%s", uri);
cgiSetVariable("refresh_page", refresh);
cgiStartHTML(cgiText(_("Set Publishing")));
/*
- * 'match_string()' - Return the number of matching characters.
+ * 'get_option_value()' - Return the value of an option.
+ *
+ * This function also handles generation of custom option values.
*/
-static int /* O - Number of matching characters */
-match_string(const char *a, /* I - First string */
- const char *b) /* I - Second string */
+static char * /* O - Value string or NULL on error */
+get_option_value(
+ ppd_file_t *ppd, /* I - PPD file */
+ const char *name, /* I - Option name */
+ char *buffer, /* I - String buffer */
+ size_t bufsize) /* I - Size of buffer */
{
- int count; /* Number of matching characters */
+ char *bufptr, /* Pointer into buffer */
+ *bufend; /* End of buffer */
+ ppd_coption_t *coption; /* Custom option */
+ ppd_cparam_t *cparam; /* Current custom parameter */
+ char keyword[256]; /* Parameter name */
+ const char *val, /* Parameter value */
+ *uval; /* Units value */
+ long integer; /* Integer value */
+ double number, /* Number value */
+ number_points; /* Number in points */
/*
- * 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...
+ * See if we have a custom option choice...
*/
- for (count = 0; *a && *b; a++, b++, count ++)
+ if ((val = cgiGetVariable(name)) == NULL)
{
/*
- * Skip leading whitespace characters...
+ * Option not found!
*/
- while (isspace(*a & 255))
- a ++;
-
- while (isspace(*b & 255))
- b ++;
-
+ return (NULL);
+ }
+ else if (_cups_strcasecmp(val, "Custom") ||
+ (coption = ppdFindCustomOption(ppd, name)) == NULL)
+ {
/*
- * Break out if we run out of characters...
+ * Not a custom choice...
*/
- if (!*a || !*b)
- break;
+ strlcpy(buffer, val, bufsize);
+ return (buffer);
+ }
- /*
- * Do a case-insensitive comparison of the next two chars...
- */
+ /*
+ * OK, we have a custom option choice, format it...
+ */
- if (tolower(*a & 255) != tolower(*b & 255))
- break;
+ *buffer = '\0';
+
+ if (!strcmp(coption->keyword, "PageSize"))
+ {
+ const char *lval; /* Length string value */
+ double width, /* Width value */
+ width_points, /* Width in points */
+ length, /* Length value */
+ length_points; /* Length in points */
+
+
+ val = cgiGetVariable("PageSize.Width");
+ lval = cgiGetVariable("PageSize.Height");
+ uval = cgiGetVariable("PageSize.Units");
+
+ if (!val || !lval || !uval ||
+ (width = strtod(val, NULL)) == 0.0 ||
+ (length = strtod(lval, NULL)) == 0.0 ||
+ (strcmp(uval, "pt") && strcmp(uval, "in") && strcmp(uval, "ft") &&
+ strcmp(uval, "cm") && strcmp(uval, "mm") && strcmp(uval, "m")))
+ return (NULL);
+
+ width_points = get_points(width, uval);
+ length_points = get_points(length, uval);
+
+ if (width_points < ppd->custom_min[0] ||
+ width_points > ppd->custom_max[0] ||
+ length_points < ppd->custom_min[1] ||
+ length_points > ppd->custom_max[1])
+ return (NULL);
+
+ snprintf(buffer, bufsize, "Custom.%gx%g%s", width, length, uval);
+ }
+ else if (cupsArrayCount(coption->params) == 1)
+ {
+ cparam = ppdFirstCustomParam(coption);
+ snprintf(keyword, sizeof(keyword), "%s.%s", coption->keyword, cparam->name);
+
+ if ((val = cgiGetVariable(keyword)) == NULL)
+ return (NULL);
+
+ switch (cparam->type)
+ {
+ case PPD_CUSTOM_UNKNOWN :
+ break;
+
+ case PPD_CUSTOM_CURVE :
+ case PPD_CUSTOM_INVCURVE :
+ case PPD_CUSTOM_REAL :
+ if ((number = strtod(val, NULL)) == 0.0 ||
+ number < cparam->minimum.custom_real ||
+ number > cparam->maximum.custom_real)
+ return (NULL);
+
+ snprintf(buffer, bufsize, "Custom.%g", number);
+ break;
+
+ case PPD_CUSTOM_INT :
+ if (!*val || (integer = strtol(val, NULL, 10)) == LONG_MIN ||
+ integer == LONG_MAX ||
+ integer < cparam->minimum.custom_int ||
+ integer > cparam->maximum.custom_int)
+ return (NULL);
+
+ snprintf(buffer, bufsize, "Custom.%ld", integer);
+ break;
+
+ case PPD_CUSTOM_POINTS :
+ snprintf(keyword, sizeof(keyword), "%s.Units", coption->keyword);
+
+ if ((number = strtod(val, NULL)) == 0.0 ||
+ (uval = cgiGetVariable(keyword)) == NULL ||
+ (strcmp(uval, "pt") && strcmp(uval, "in") && strcmp(uval, "ft") &&
+ strcmp(uval, "cm") && strcmp(uval, "mm") && strcmp(uval, "m")))
+ return (NULL);
+
+ number_points = get_points(number, uval);
+ if (number_points < cparam->minimum.custom_points ||
+ number_points > cparam->maximum.custom_points)
+ return (NULL);
+
+ snprintf(buffer, bufsize, "Custom.%g%s", number, uval);
+ break;
+
+ case PPD_CUSTOM_PASSCODE :
+ for (uval = val; *uval; uval ++)
+ if (!isdigit(*uval & 255))
+ return (NULL);
+
+ case PPD_CUSTOM_PASSWORD :
+ case PPD_CUSTOM_STRING :
+ integer = (long)strlen(val);
+ if (integer < cparam->minimum.custom_string ||
+ integer > cparam->maximum.custom_string)
+ return (NULL);
+
+ snprintf(buffer, bufsize, "Custom.%s", val);
+ break;
+ }
+ }
+ else
+ {
+ const char *prefix = "{"; /* Prefix string */
+
+
+ bufptr = buffer;
+ bufend = buffer + bufsize;
+
+ for (cparam = ppdFirstCustomParam(coption);
+ cparam;
+ cparam = ppdNextCustomParam(coption))
+ {
+ snprintf(keyword, sizeof(keyword), "%s.%s", coption->keyword,
+ cparam->name);
+
+ if ((val = cgiGetVariable(keyword)) == NULL)
+ return (NULL);
+
+ snprintf(bufptr, (size_t)(bufend - bufptr), "%s%s=", prefix, cparam->name);
+ bufptr += strlen(bufptr);
+ prefix = " ";
+
+ switch (cparam->type)
+ {
+ case PPD_CUSTOM_UNKNOWN :
+ break;
+
+ case PPD_CUSTOM_CURVE :
+ case PPD_CUSTOM_INVCURVE :
+ case PPD_CUSTOM_REAL :
+ if ((number = strtod(val, NULL)) == 0.0 ||
+ number < cparam->minimum.custom_real ||
+ number > cparam->maximum.custom_real)
+ return (NULL);
+
+ snprintf(bufptr, (size_t)(bufend - bufptr), "%g", number);
+ break;
+
+ case PPD_CUSTOM_INT :
+ if (!*val || (integer = strtol(val, NULL, 10)) == LONG_MIN ||
+ integer == LONG_MAX ||
+ integer < cparam->minimum.custom_int ||
+ integer > cparam->maximum.custom_int)
+ return (NULL);
+
+ snprintf(bufptr, (size_t)(bufend - bufptr), "%ld", integer);
+ break;
+
+ case PPD_CUSTOM_POINTS :
+ snprintf(keyword, sizeof(keyword), "%s.Units", coption->keyword);
+
+ if ((number = strtod(val, NULL)) == 0.0 ||
+ (uval = cgiGetVariable(keyword)) == NULL ||
+ (strcmp(uval, "pt") && strcmp(uval, "in") &&
+ strcmp(uval, "ft") && strcmp(uval, "cm") &&
+ strcmp(uval, "mm") && strcmp(uval, "m")))
+ return (NULL);
+
+ number_points = get_points(number, uval);
+ if (number_points < cparam->minimum.custom_points ||
+ number_points > cparam->maximum.custom_points)
+ return (NULL);
+
+ snprintf(bufptr, (size_t)(bufend - bufptr), "%g%s", number, uval);
+ break;
+
+ case PPD_CUSTOM_PASSCODE :
+ for (uval = val; *uval; uval ++)
+ if (!isdigit(*uval & 255))
+ return (NULL);
+
+ case PPD_CUSTOM_PASSWORD :
+ case PPD_CUSTOM_STRING :
+ integer = (long)strlen(val);
+ if (integer < cparam->minimum.custom_string ||
+ integer > cparam->maximum.custom_string)
+ return (NULL);
+
+ if ((bufptr + 2) > bufend)
+ return (NULL);
+
+ bufend --;
+ *bufptr++ = '\"';
+
+ while (*val && bufptr < bufend)
+ {
+ if (*val == '\\' || *val == '\"')
+ {
+ if ((bufptr + 1) >= bufend)
+ return (NULL);
+
+ *bufptr++ = '\\';
+ }
+
+ *bufptr++ = *val++;
+ }
+
+ if (bufptr >= bufend)
+ return (NULL);
+
+ *bufptr++ = '\"';
+ *bufptr = '\0';
+ bufend ++;
+ break;
+ }
+
+ bufptr += strlen(bufptr);
+ }
+
+ if (bufptr == buffer || (bufend - bufptr) < 2)
+ return (NULL);
+
+ memcpy(bufptr, "}", 2);
}
- return (count);
+ return (buffer);
}
-
+
+/*
+ * 'get_points()' - Get a value in points.
+ */
+
+static double /* O - Number in points */
+get_points(double number, /* I - Original number */
+ const char *uval) /* I - Units */
+{
+ if (!strcmp(uval, "mm")) /* Millimeters */
+ return (number * 72.0 / 25.4);
+ else if (!strcmp(uval, "cm")) /* Centimeters */
+ return (number * 72.0 / 2.54);
+ else if (!strcmp(uval, "in")) /* Inches */
+ return (number * 72.0);
+ else if (!strcmp(uval, "ft")) /* Feet */
+ return (number * 72.0 * 12.0);
+ else if (!strcmp(uval, "m")) /* Meters */
+ return (number * 72.0 / 0.0254);
+ else /* Points */
+ return (number);
+}
+
+
/*
- * End of "$Id: admin.c 4943 2006-01-18 20:30:42Z mike $".
+ * 'get_printer_ppd()' - Get an IPP Everywhere PPD file for the given URI.
*/
+
+static char * /* O - Filename or NULL */
+get_printer_ppd(const char *uri, /* I - Printer URI */
+ char *buffer, /* I - Filename buffer */
+ size_t bufsize) /* I - Size of filename buffer */
+{
+ http_t *http; /* Connection to printer */
+ ipp_t *request, /* Get-Printer-Attributes request */
+ *response; /* Get-Printer-Attributes response */
+ char resolved[1024], /* Resolved URI */
+ scheme[32], /* URI scheme */
+ userpass[256], /* Username:password */
+ host[256], /* Hostname */
+ resource[256]; /* Resource path */
+ int port; /* Port number */
+ static const char * const pattrs[] = /* Printer attributes we need */
+ {
+ "all",
+ "media-col-database"
+ };
+
+
+ /*
+ * Connect to the printer...
+ */
+
+ if (strstr(uri, "._tcp"))
+ {
+ /*
+ * Resolve URI...
+ */
+
+ if (!_httpResolveURI(uri, resolved, sizeof(resolved), _HTTP_RESOLVE_DEFAULT, NULL, NULL))
+ {
+ fprintf(stderr, "ERROR: Unable to resolve \"%s\".\n", uri);
+ return (NULL);
+ }
+
+ uri = resolved;
+ }
+
+ if (httpSeparateURI(HTTP_URI_CODING_ALL, uri, scheme, sizeof(scheme), userpass, sizeof(userpass), host, sizeof(host), &port, resource, sizeof(resource)) < HTTP_URI_STATUS_OK)
+ {
+ fprintf(stderr, "ERROR: Bad printer URI \"%s\".\n", uri);
+ return (NULL);
+ }
+
+ http = httpConnect2(host, port, NULL, AF_UNSPEC, !strcmp(scheme, "ipps") ? HTTP_ENCRYPTION_ALWAYS : HTTP_ENCRYPTION_IF_REQUESTED, 1, 30000, NULL);
+ if (!http)
+ {
+ fprintf(stderr, "ERROR: Unable to connect to \"%s:%d\": %s\n", host, port, cupsLastErrorString());
+ return (NULL);
+ }
+
+ /*
+ * Send a Get-Printer-Attributes request...
+ */
+
+ request = ippNewRequest(IPP_OP_GET_PRINTER_ATTRIBUTES);
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, uri);
+ ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, "requested-attributes", (int)(sizeof(pattrs) / sizeof(pattrs[0])), NULL, pattrs);
+ response = cupsDoRequest(http, request, resource);
+
+ if (!_ppdCreateFromIPP(buffer, bufsize, response))
+ fprintf(stderr, "ERROR: Unable to create PPD file: %s\n", strerror(errno));
+
+ ippDelete(response);
+ httpClose(http);
+
+ if (buffer[0])
+ return (buffer);
+ else
+ return (NULL);
+}