]> git.ipfire.org Git - thirdparty/cups.git/blame - cgi-bin/admin.c
Load cups into easysw/current.
[thirdparty/cups.git] / cgi-bin / admin.c
CommitLineData
ef416fc2 1/*
323c5de1 2 * "$Id: admin.c 6440 2007-04-03 23:17:17Z mike $"
ef416fc2 3 *
4 * Administration CGI for the Common UNIX Printing System (CUPS).
5 *
f7deaa1a 6 * Copyright 1997-2007 by Easy Software Products.
ef416fc2 7 *
8 * These coded instructions, statements, and computer programs are the
9 * property of Easy Software Products and are protected by Federal
10 * copyright law. Distribution and use rights are outlined in the file
11 * "LICENSE.txt" which should have been included with this file. If this
12 * file is missing or damaged please contact Easy Software Products
13 * at:
14 *
15 * Attn: CUPS Licensing Information
16 * Easy Software Products
17 * 44141 Airport View Drive, Suite 204
18 * Hollywood, Maryland 20636 USA
19 *
20 * Voice: (301) 373-9600
21 * EMail: cups-info@cups.org
22 * WWW: http://www.cups.org
23 *
24 * Contents:
25 *
26 * main() - Main entry for CGI.
f7deaa1a 27 * do_add_rss_subscription() - Add a RSS subscription.
ef416fc2 28 * do_am_class() - Add or modify a class.
29 * do_am_printer() - Add or modify a printer.
f7deaa1a 30 * do_cancel_subscription() - Cancel a subscription.
ef416fc2 31 * do_config_server() - Configure server settings.
32 * do_delete_class() - Delete a class...
33 * do_delete_printer() - Delete a printer...
fa73b229 34 * do_export() - Export printers to Samba...
323c5de1 35 * do_list_printers() - List available printers...
ef416fc2 36 * do_menu() - Show the main menu...
37 * do_printer_op() - Do a printer operation.
38 * do_set_allowed_users() - Set the allowed/denied users for a queue.
323c5de1 39 * do_set_options() - Configure the default options for a queue.
ef416fc2 40 * do_set_sharing() - Set printer-is-shared value...
41 * match_string() - Return the number of matching characters.
42 */
43
44/*
45 * Include necessary headers...
46 */
47
48#include "cgi-private.h"
757d2cad 49#include <cups/adminutil.h>
ef416fc2 50#include <cups/file.h>
51#include <errno.h>
fa73b229 52#include <unistd.h>
53#include <fcntl.h>
54#include <sys/wait.h>
ef416fc2 55
56
57/*
58 * Local functions...
59 */
60
f7deaa1a 61static void do_add_rss_subscription(http_t *http);
fa73b229 62static void do_am_class(http_t *http, int modify);
63static void do_am_printer(http_t *http, int modify);
f7deaa1a 64static void do_cancel_subscription(http_t *http);
323c5de1 65static void do_set_options(http_t *http, int is_class);
fa73b229 66static void do_config_server(http_t *http);
67static void do_delete_class(http_t *http);
68static void do_delete_printer(http_t *http);
69static void do_export(http_t *http);
323c5de1 70static void do_list_printers(http_t *http);
fa73b229 71static void do_menu(http_t *http);
72static void do_printer_op(http_t *http,
ef416fc2 73 ipp_op_t op, const char *title);
fa73b229 74static void do_set_allowed_users(http_t *http);
75static void do_set_sharing(http_t *http);
ef416fc2 76static int match_string(const char *a, const char *b);
77
78
79/*
80 * 'main()' - Main entry for CGI.
81 */
82
83int /* O - Exit status */
84main(int argc, /* I - Number of command-line arguments */
85 char *argv[]) /* I - Command-line arguments */
86{
ef416fc2 87 http_t *http; /* Connection to the server */
88 const char *op; /* Operation name */
89
90
ef416fc2 91 /*
92 * Connect to the HTTP server...
93 */
94
bd7854cb 95 fputs("DEBUG: admin.cgi started...\n", stderr);
96
ef416fc2 97 http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption());
98
a4d04587 99 if (!http)
100 {
101 perror("ERROR: Unable to connect to cupsd");
f301802f 102 fprintf(stderr, "DEBUG: cupsServer()=\"%s\"\n",
103 cupsServer() ? cupsServer() : "(null)");
a4d04587 104 fprintf(stderr, "DEBUG: ippPort()=%d\n", ippPort());
105 fprintf(stderr, "DEBUG: cupsEncryption()=%d\n", cupsEncryption());
106 exit(1);
107 }
108
bd7854cb 109 fprintf(stderr, "DEBUG: http=%p\n", http);
110
ef416fc2 111 /*
112 * Set the web interface section...
113 */
114
115 cgiSetVariable("SECTION", "admin");
116
117 /*
118 * See if we have form data...
119 */
120
121 if (!cgiInitialize())
122 {
123 /*
124 * Nope, send the administration menu...
125 */
126
bd7854cb 127 fputs("DEBUG: No form data, showing main menu...\n", stderr);
128
fa73b229 129 do_menu(http);
ef416fc2 130 }
131 else if ((op = cgiGetVariable("OP")) != NULL)
132 {
133 /*
134 * Do the operation...
135 */
136
bd7854cb 137 fprintf(stderr, "DEBUG: op=\"%s\"...\n", op);
138
ef416fc2 139 if (!strcmp(op, "redirect"))
140 {
141 const char *url; /* Redirection URL... */
d6ae789d 142 char prefix[1024]; /* URL prefix */
ef416fc2 143
144
d6ae789d 145 if (getenv("HTTPS"))
146 snprintf(prefix, sizeof(prefix), "https://%s:%s",
147 getenv("SERVER_NAME"), getenv("SERVER_PORT"));
148 else
149 snprintf(prefix, sizeof(prefix), "http://%s:%s",
150 getenv("SERVER_NAME"), getenv("SERVER_PORT"));
151
ef416fc2 152 if ((url = cgiGetVariable("URL")) != NULL)
d6ae789d 153 printf("Location: %s%s\n\n", prefix, url);
ef416fc2 154 else
d6ae789d 155 printf("Location: %s/admin\n\n", prefix);
ef416fc2 156 }
157 else if (!strcmp(op, "start-printer"))
fa73b229 158 do_printer_op(http, IPP_RESUME_PRINTER, cgiText(_("Start Printer")));
ef416fc2 159 else if (!strcmp(op, "stop-printer"))
fa73b229 160 do_printer_op(http, IPP_PAUSE_PRINTER, cgiText(_("Stop Printer")));
ef416fc2 161 else if (!strcmp(op, "start-class"))
fa73b229 162 do_printer_op(http, IPP_RESUME_PRINTER, cgiText(_("Start Class")));
ef416fc2 163 else if (!strcmp(op, "stop-class"))
fa73b229 164 do_printer_op(http, IPP_PAUSE_PRINTER, cgiText(_("Stop Class")));
ef416fc2 165 else if (!strcmp(op, "accept-jobs"))
fa73b229 166 do_printer_op(http, CUPS_ACCEPT_JOBS, cgiText(_("Accept Jobs")));
ef416fc2 167 else if (!strcmp(op, "reject-jobs"))
fa73b229 168 do_printer_op(http, CUPS_REJECT_JOBS, cgiText(_("Reject Jobs")));
ef416fc2 169 else if (!strcmp(op, "purge-jobs"))
fa73b229 170 do_printer_op(http, IPP_PURGE_JOBS, cgiText(_("Purge Jobs")));
ef416fc2 171 else if (!strcmp(op, "set-allowed-users"))
fa73b229 172 do_set_allowed_users(http);
ef416fc2 173 else if (!strcmp(op, "set-as-default"))
fa73b229 174 do_printer_op(http, CUPS_SET_DEFAULT, cgiText(_("Set As Default")));
ef416fc2 175 else if (!strcmp(op, "set-sharing"))
fa73b229 176 do_set_sharing(http);
323c5de1 177 else if (!strcmp(op, "list-available-printers"))
178 do_list_printers(http);
ef416fc2 179 else if (!strcmp(op, "add-class"))
fa73b229 180 do_am_class(http, 0);
ef416fc2 181 else if (!strcmp(op, "add-printer"))
fa73b229 182 do_am_printer(http, 0);
ef416fc2 183 else if (!strcmp(op, "modify-class"))
fa73b229 184 do_am_class(http, 1);
ef416fc2 185 else if (!strcmp(op, "modify-printer"))
fa73b229 186 do_am_printer(http, 1);
ef416fc2 187 else if (!strcmp(op, "delete-class"))
fa73b229 188 do_delete_class(http);
ef416fc2 189 else if (!strcmp(op, "delete-printer"))
fa73b229 190 do_delete_printer(http);
323c5de1 191 else if (!strcmp(op, "set-class-options"))
192 do_set_options(http, 1);
ef416fc2 193 else if (!strcmp(op, "set-printer-options"))
323c5de1 194 do_set_options(http, 0);
ef416fc2 195 else if (!strcmp(op, "config-server"))
fa73b229 196 do_config_server(http);
197 else if (!strcmp(op, "export-samba"))
198 do_export(http);
f7deaa1a 199 else if (!strcmp(op, "add-rss-subscription"))
200 do_add_rss_subscription(http);
201 else if (!strcmp(op, "cancel-subscription"))
202 do_cancel_subscription(http);
ef416fc2 203 else
204 {
205 /*
206 * Bad operation code... Display an error...
207 */
208
fa73b229 209 cgiStartHTML(cgiText(_("Administration")));
210 cgiCopyTemplateLang("error-op.tmpl");
ef416fc2 211 cgiEndHTML();
212 }
ef416fc2 213 }
214 else
215 {
216 /*
217 * Form data but no operation code... Display an error...
218 */
219
fa73b229 220 cgiStartHTML(cgiText(_("Administration")));
221 cgiCopyTemplateLang("error-op.tmpl");
ef416fc2 222 cgiEndHTML();
223 }
224
225 /*
fa73b229 226 * Close the HTTP server connection...
ef416fc2 227 */
228
fa73b229 229 httpClose(http);
ef416fc2 230
231 /*
232 * Return with no errors...
233 */
234
235 return (0);
236}
237
238
f7deaa1a 239/*
240 * 'do_add_rss_subscription()' - Add a RSS subscription.
241 */
242
243static void
244do_add_rss_subscription(http_t *http) /* I - HTTP connection */
245{
246 ipp_t *request, /* IPP request data */
247 *response; /* IPP response data */
248 char rss_uri[1024]; /* RSS notify-recipient URI */
249 int num_events; /* Number of events */
250 const char *events[12], /* Subscribed events */
251 *subscription_name, /* Subscription name */
252 *printer_uri, /* Printer URI */
253 *ptr, /* Pointer into name */
254 *user; /* Username */
255 int max_events; /* Maximum number of events */
256
257
258 /*
259 * See if we have all of the required information...
260 */
261
262 subscription_name = cgiGetVariable("SUBSCRIPTION_NAME");
263 printer_uri = cgiGetVariable("PRINTER_URI");
264 num_events = 0;
265
266 if (cgiGetVariable("EVENT_JOB_CREATED"))
267 events[num_events ++] = "job-created";
268 if (cgiGetVariable("EVENT_JOB_COMPLETED"))
269 events[num_events ++] = "job-completed";
270 if (cgiGetVariable("EVENT_JOB_STOPPED"))
271 events[num_events ++] = "job-stopped";
272 if (cgiGetVariable("EVENT_JOB_CONFIG_CHANGED"))
273 events[num_events ++] = "job-config-changed";
274 if (cgiGetVariable("EVENT_PRINTER_STOPPED"))
275 events[num_events ++] = "printer-stopped";
276 if (cgiGetVariable("EVENT_PRINTER_ADDED"))
277 events[num_events ++] = "printer-added";
278 if (cgiGetVariable("EVENT_PRINTER_MODIFIED"))
279 events[num_events ++] = "printer-modified";
280 if (cgiGetVariable("EVENT_PRINTER_DELETED"))
281 events[num_events ++] = "printer-deleted";
282 if (cgiGetVariable("EVENT_SERVER_STARTED"))
283 events[num_events ++] = "server-started";
284 if (cgiGetVariable("EVENT_SERVER_STOPPED"))
285 events[num_events ++] = "server-stopped";
286 if (cgiGetVariable("EVENT_SERVER_RESTARTED"))
287 events[num_events ++] = "server-restarted";
288 if (cgiGetVariable("EVENT_SERVER_AUDIT"))
289 events[num_events ++] = "server-audit";
290
291 if ((ptr = cgiGetVariable("MAX_EVENTS")) != NULL)
292 max_events = atoi(ptr);
293 else
294 max_events = 0;
295
296 if (!subscription_name || !printer_uri || !num_events ||
297 max_events <= 0 || max_events > 9999)
298 {
299 /*
300 * Don't have everything we need, so get the available printers
301 * and classes and (re)show the add page...
302 */
303
304 request = ippNewRequest(CUPS_GET_PRINTERS);
305 response = cupsDoRequest(http, request, "/");
306
307 cgiSetIPPVars(response, NULL, NULL, NULL, 0);
308
309 ippDelete(response);
310
311 cgiStartHTML(cgiText(_("Add RSS Subscription")));
312
313 cgiCopyTemplateLang("add-rss-subscription.tmpl");
314
315 cgiEndHTML();
316 return;
317 }
318
319 /*
320 * Validate the subscription name...
321 */
322
323 for (ptr = subscription_name; *ptr; ptr ++)
324 if ((*ptr >= 0 && *ptr <= ' ') || *ptr == 127 || *ptr == '/' ||
325 *ptr == '?' || *ptr == '#')
326 break;
327
328 if (*ptr)
329 {
330 cgiSetVariable("ERROR",
331 cgiText(_("The subscription name may not "
332 "contain spaces, slashes (/), question marks (?), "
333 "or the pound sign (#).")));
334 cgiStartHTML(_("Add RSS Subscription"));
335 cgiCopyTemplateLang("error.tmpl");
336 cgiEndHTML();
337 return;
338 }
339
340 /*
341 * Add the subscription...
342 */
343
344 ptr = subscription_name + strlen(subscription_name) - 4;
345 if (ptr < subscription_name || strcmp(ptr, ".rss"))
346 httpAssembleURIf(HTTP_URI_CODING_ALL, rss_uri, sizeof(rss_uri), "rss",
347 NULL, NULL, 0, "/%s.rss?max_events=%d", subscription_name,
348 max_events);
349 else
350 httpAssembleURIf(HTTP_URI_CODING_ALL, rss_uri, sizeof(rss_uri), "rss",
351 NULL, NULL, 0, "/%s?max_events=%d", subscription_name,
352 max_events);
353
354 request = ippNewRequest(IPP_CREATE_PRINTER_SUBSCRIPTION);
355
356 if (!strcasecmp(printer_uri, "#ALL#"))
357 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
358 NULL, "ipp://localhost/");
359 else
360 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
361 NULL, printer_uri);
362
363 if ((user = getenv("REMOTE_USER")) == NULL)
364 user = "guest";
365
366 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
367 NULL, user);
368
7594b224 369 ippAddString(request, IPP_TAG_SUBSCRIPTION, IPP_TAG_URI,
370 "notify-recipient-uri", NULL, rss_uri);
f7deaa1a 371 ippAddStrings(request, IPP_TAG_SUBSCRIPTION, IPP_TAG_KEYWORD, "notify-events",
372 num_events, NULL, events);
373 ippAddInteger(request, IPP_TAG_SUBSCRIPTION, IPP_TAG_INTEGER,
374 "notify-lease-duration", 0);
375
376 ippDelete(cupsDoRequest(http, request, "/"));
377
378 if (cupsLastError() > IPP_OK_CONFLICT)
379 {
380 cgiStartHTML(_("Add RSS Subscription"));
381 cgiShowIPPError(_("Unable to add RSS subscription:"));
382 }
383 else
384 {
385 /*
386 * Redirect successful updates back to the admin page...
387 */
388
389 cgiSetVariable("refresh_page", "5;URL=/admin");
390 cgiStartHTML(_("Add RSS Subscription"));
391 cgiCopyTemplateLang("subscription-added.tmpl");
392 }
393
394 cgiEndHTML();
395}
396
397
ef416fc2 398/*
399 * 'do_am_class()' - Add or modify a class.
400 */
401
402static void
fa73b229 403do_am_class(http_t *http, /* I - HTTP connection */
404 int modify) /* I - Modify the printer? */
ef416fc2 405{
406 int i, j; /* Looping vars */
407 int element; /* Element number */
408 int num_printers; /* Number of printers */
409 ipp_t *request, /* IPP request */
410 *response; /* IPP response */
411 ipp_attribute_t *attr; /* member-uris attribute */
ef416fc2 412 char uri[HTTP_MAX_URI]; /* Device or printer URI */
413 const char *name, /* Pointer to class name */
414 *ptr; /* Pointer to CGI variable */
415 const char *title; /* Title of page */
416 static const char * const pattrs[] = /* Requested printer attributes */
417 {
418 "member-names",
419 "printer-info",
420 "printer-location"
421 };
422
423
fa73b229 424 title = cgiText(modify ? _("Modify Class") : _("Add Class"));
ef416fc2 425 name = cgiGetVariable("PRINTER_NAME");
426
427 if (cgiGetVariable("PRINTER_LOCATION") == NULL)
428 {
429 /*
430 * Build a CUPS_GET_PRINTERS request, which requires the
431 * following attributes:
432 *
433 * attributes-charset
434 * attributes-natural-language
ef416fc2 435 */
436
fa73b229 437 request = ippNewRequest(CUPS_GET_PRINTERS);
ef416fc2 438
ef416fc2 439 /*
440 * Do the request and get back a response...
441 */
442
443 if ((response = cupsDoRequest(http, request, "/")) != NULL)
444 {
445 /*
446 * Create MEMBER_URIS and MEMBER_NAMES arrays...
447 */
448
449 for (element = 0, attr = response->attrs;
450 attr != NULL;
451 attr = attr->next)
452 if (attr->name && !strcmp(attr->name, "printer-uri-supported"))
453 {
454 if ((ptr = strrchr(attr->values[0].string.text, '/')) != NULL &&
455 (!name || strcasecmp(name, ptr + 1)))
456 {
457 /*
458 * Don't show the current class...
459 */
460
461 cgiSetArray("MEMBER_URIS", element, attr->values[0].string.text);
462 element ++;
463 }
464 }
465
466 for (element = 0, attr = response->attrs;
467 attr != NULL;
468 attr = attr->next)
469 if (attr->name && !strcmp(attr->name, "printer-name"))
470 {
471 if (!name || strcasecmp(name, attr->values[0].string.text))
472 {
473 /*
474 * Don't show the current class...
475 */
476
477 cgiSetArray("MEMBER_NAMES", element, attr->values[0].string.text);
478 element ++;
479 }
480 }
481
482 num_printers = cgiGetSize("MEMBER_URIS");
483
484 ippDelete(response);
485 }
486 else
487 num_printers = 0;
488
489 if (modify)
490 {
491 /*
492 * Build an IPP_GET_PRINTER_ATTRIBUTES request, which requires the
493 * following attributes:
494 *
495 * attributes-charset
496 * attributes-natural-language
497 * printer-uri
498 */
499
fa73b229 500 request = ippNewRequest(IPP_GET_PRINTER_ATTRIBUTES);
ef416fc2 501
a4d04587 502 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
503 "localhost", 0, "/classes/%s", name);
ef416fc2 504 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
505 NULL, uri);
506
507 ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
508 "requested-attributes",
509 (int)(sizeof(pattrs) / sizeof(pattrs[0])),
510 NULL, pattrs);
511
512 /*
513 * Do the request and get back a response...
514 */
515
516 if ((response = cupsDoRequest(http, request, "/")) != NULL)
517 {
480ef0fe 518 if ((attr = ippFindAttribute(response, "member-names",
519 IPP_TAG_NAME)) != NULL)
ef416fc2 520 {
521 /*
522 * Mark any current members in the class...
523 */
524
525 for (j = 0; j < num_printers; j ++)
526 cgiSetArray("MEMBER_SELECTED", j, "");
527
528 for (i = 0; i < attr->num_values; i ++)
529 {
530 for (j = 0; j < num_printers; j ++)
531 {
532 if (!strcasecmp(attr->values[i].string.text,
533 cgiGetArray("MEMBER_NAMES", j)))
534 {
535 cgiSetArray("MEMBER_SELECTED", j, "SELECTED");
536 break;
537 }
538 }
539 }
540 }
541
542 if ((attr = ippFindAttribute(response, "printer-info",
543 IPP_TAG_TEXT)) != NULL)
544 cgiSetVariable("PRINTER_INFO", attr->values[0].string.text);
545
546 if ((attr = ippFindAttribute(response, "printer-location",
547 IPP_TAG_TEXT)) != NULL)
548 cgiSetVariable("PRINTER_LOCATION", attr->values[0].string.text);
549
550 ippDelete(response);
551 }
552
553 /*
554 * Update the location and description of an existing printer...
555 */
556
557 cgiStartHTML(title);
558 cgiCopyTemplateLang("modify-class.tmpl");
559 }
560 else
561 {
562 /*
563 * Get the name, location, and description for a new printer...
564 */
565
566 cgiStartHTML(title);
567 cgiCopyTemplateLang("add-class.tmpl");
568 }
569
570 cgiEndHTML();
571
572 return;
573 }
574
575 for (ptr = name; *ptr; ptr ++)
576 if ((*ptr >= 0 && *ptr <= ' ') || *ptr == 127 || *ptr == '/' || *ptr == '#')
577 break;
578
579 if (*ptr || ptr == name || strlen(name) > 127)
580 {
fa73b229 581 cgiSetVariable("ERROR",
582 cgiText(_("The class name may only contain up to "
583 "127 printable characters and may not "
584 "contain spaces, slashes (/), or the "
585 "pound sign (#).")));
ef416fc2 586 cgiStartHTML(title);
587 cgiCopyTemplateLang("error.tmpl");
588 cgiEndHTML();
589 return;
590 }
591
592 /*
593 * Build a CUPS_ADD_CLASS request, which requires the following
594 * attributes:
595 *
596 * attributes-charset
597 * attributes-natural-language
598 * printer-uri
599 * printer-location
600 * printer-info
601 * printer-is-accepting-jobs
602 * printer-state
603 * member-uris
604 */
605
fa73b229 606 request = ippNewRequest(CUPS_ADD_CLASS);
ef416fc2 607
a4d04587 608 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
609 "localhost", 0, "/classes/%s",
610 cgiGetVariable("PRINTER_NAME"));
ef416fc2 611 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
612 NULL, uri);
613
614 ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-location",
615 NULL, cgiGetVariable("PRINTER_LOCATION"));
616
617 ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-info",
618 NULL, cgiGetVariable("PRINTER_INFO"));
619
620 ippAddBoolean(request, IPP_TAG_PRINTER, "printer-is-accepting-jobs", 1);
621
622 ippAddInteger(request, IPP_TAG_PRINTER, IPP_TAG_ENUM, "printer-state",
623 IPP_PRINTER_IDLE);
624
625 if ((num_printers = cgiGetSize("MEMBER_URIS")) > 0)
626 {
627 attr = ippAddStrings(request, IPP_TAG_PRINTER, IPP_TAG_URI, "member-uris",
628 num_printers, NULL, NULL);
629 for (i = 0; i < num_printers; i ++)
630 attr->values[i].string.text = strdup(cgiGetArray("MEMBER_URIS", i));
631 }
632
633 /*
634 * Do the request and get back a response...
635 */
636
fa73b229 637 ippDelete(cupsDoRequest(http, request, "/admin/"));
ef416fc2 638
fa73b229 639 if (cupsLastError() > IPP_OK_CONFLICT)
ef416fc2 640 {
641 cgiStartHTML(title);
fa73b229 642 cgiShowIPPError(modify ? _("Unable to modify class:") :
643 _("Unable to add class:"));
ef416fc2 644 }
645 else
646 {
647 /*
648 * Redirect successful updates back to the class page...
649 */
650
651 char refresh[1024]; /* Refresh URL */
652
653 cgiFormEncode(uri, name, sizeof(uri));
f301802f 654 snprintf(refresh, sizeof(refresh), "5;URL=/admin/?OP=redirect&URL=/classes/%s",
ef416fc2 655 uri);
656 cgiSetVariable("refresh_page", refresh);
657
658 cgiStartHTML(title);
659
660 if (modify)
661 cgiCopyTemplateLang("class-modified.tmpl");
662 else
663 cgiCopyTemplateLang("class-added.tmpl");
664 }
665
666 cgiEndHTML();
667}
668
669
670/*
671 * 'do_am_printer()' - Add or modify a printer.
672 */
673
674static void
fa73b229 675do_am_printer(http_t *http, /* I - HTTP connection */
676 int modify) /* I - Modify the printer? */
ef416fc2 677{
678 int i; /* Looping var */
89d46774 679 ipp_attribute_t *attr; /* Current attribute */
ef416fc2 680 ipp_t *request, /* IPP request */
681 *response, /* IPP response */
682 *oldinfo; /* Old printer information */
ef416fc2 683 const cgi_file_t *file; /* Uploaded file, if any */
684 const char *var; /* CGI variable */
685 char uri[HTTP_MAX_URI], /* Device or printer URI */
686 *uriptr; /* Pointer into URI */
687 int maxrate; /* Maximum baud rate */
688 char baudrate[255]; /* Baud rate string */
689 const char *name, /* Pointer to class name */
690 *ptr; /* Pointer to CGI variable */
691 const char *title; /* Title of page */
692 static int baudrates[] = /* Baud rates */
693 {
694 1200,
695 2400,
696 4800,
697 9600,
698 19200,
699 38400,
700 57600,
701 115200,
702 230400,
703 460800
704 };
705
706
f301802f 707 ptr = cgiGetVariable("DEVICE_URI");
fa73b229 708 fprintf(stderr, "DEBUG: do_am_printer: DEVICE_URI=\"%s\"\n",
f301802f 709 ptr ? ptr : "(null)");
fa73b229 710
711 title = cgiText(modify ? _("Modify Printer") : _("Add Printer"));
ef416fc2 712
713 if (modify)
714 {
715 /*
716 * Build an IPP_GET_PRINTER_ATTRIBUTES request, which requires the
717 * following attributes:
718 *
719 * attributes-charset
720 * attributes-natural-language
721 * printer-uri
722 */
723
fa73b229 724 request = ippNewRequest(IPP_GET_PRINTER_ATTRIBUTES);
ef416fc2 725
a4d04587 726 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
727 "localhost", 0, "/printers/%s",
728 cgiGetVariable("PRINTER_NAME"));
ef416fc2 729 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
730 NULL, uri);
731
732 /*
733 * Do the request and get back a response...
734 */
735
736 oldinfo = cupsDoRequest(http, request, "/");
737 }
738 else
739 oldinfo = NULL;
740
741 if ((name = cgiGetVariable("PRINTER_NAME")) == NULL ||
742 cgiGetVariable("PRINTER_LOCATION") == NULL)
743 {
744 cgiStartHTML(title);
745
746 if (modify)
747 {
748 /*
749 * Update the location and description of an existing printer...
750 */
751
752 if (oldinfo)
753 cgiSetIPPVars(oldinfo, NULL, NULL, NULL, 0);
754
755 cgiCopyTemplateLang("modify-printer.tmpl");
756 }
757 else
758 {
759 /*
760 * Get the name, location, and description for a new printer...
761 */
762
763 cgiCopyTemplateLang("add-printer.tmpl");
764 }
765
766 cgiEndHTML();
767
768 if (oldinfo)
769 ippDelete(oldinfo);
770
771 return;
772 }
773
774 for (ptr = name; *ptr; ptr ++)
775 if ((*ptr >= 0 && *ptr <= ' ') || *ptr == 127 || *ptr == '/' || *ptr == '#')
776 break;
777
778 if (*ptr || ptr == name || strlen(name) > 127)
779 {
fa73b229 780 cgiSetVariable("ERROR",
781 cgiText(_("The printer name may only contain up to "
782 "127 printable characters and may not "
783 "contain spaces, slashes (/), or the "
784 "pound sign (#).")));
ef416fc2 785 cgiStartHTML(title);
786 cgiCopyTemplateLang("error.tmpl");
787 cgiEndHTML();
788 return;
789 }
790
791 file = cgiGetFile();
792
793 if (file)
794 {
795 fprintf(stderr, "DEBUG: file->tempfile=%s\n", file->tempfile);
796 fprintf(stderr, "DEBUG: file->name=%s\n", file->name);
797 fprintf(stderr, "DEBUG: file->filename=%s\n", file->filename);
798 fprintf(stderr, "DEBUG: file->mimetype=%s\n", file->mimetype);
799 }
800
801 if ((var = cgiGetVariable("DEVICE_URI")) == NULL)
802 {
803 /*
804 * Build a CUPS_GET_DEVICES request, which requires the following
805 * attributes:
806 *
807 * attributes-charset
808 * attributes-natural-language
809 * printer-uri
810 */
811
a4d04587 812 fputs("DEBUG: Getting list of devices...\n", stderr);
813
fa73b229 814 request = ippNewRequest(CUPS_GET_DEVICES);
ef416fc2 815
816 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
817 NULL, "ipp://localhost/printers/");
818
819 /*
820 * Do the request and get back a response...
821 */
822
823 if ((response = cupsDoRequest(http, request, "/")) != NULL)
824 {
a4d04587 825 fputs("DEBUG: Got device list!\n", stderr);
826
ef416fc2 827 cgiSetIPPVars(response, NULL, NULL, NULL, 0);
828 ippDelete(response);
829 }
a4d04587 830 else
831 fprintf(stderr,
832 "ERROR: CUPS-Get-Devices request failed with status %x: %s\n",
833 cupsLastError(), cupsLastErrorString());
ef416fc2 834
835 /*
836 * Let the user choose...
837 */
838
839 if ((attr = ippFindAttribute(oldinfo, "device-uri", IPP_TAG_URI)) != NULL)
840 {
841 strlcpy(uri, attr->values[0].string.text, sizeof(uri));
842 if ((uriptr = strchr(uri, ':')) != NULL && strncmp(uriptr, "://", 3) == 0)
843 *uriptr = '\0';
844
845 cgiSetVariable("CURRENT_DEVICE_URI", attr->values[0].string.text);
846 cgiSetVariable("CURRENT_DEVICE_SCHEME", uri);
847 }
848
849 cgiStartHTML(title);
850 cgiCopyTemplateLang("choose-device.tmpl");
851 cgiEndHTML();
852 }
853 else if (strchr(var, '/') == NULL)
854 {
855 if ((attr = ippFindAttribute(oldinfo, "device-uri", IPP_TAG_URI)) != NULL)
856 {
857 /*
858 * Set the current device URI for the form to the old one...
859 */
860
861 if (strncmp(attr->values[0].string.text, var, strlen(var)) == 0)
862 cgiSetVariable("DEVICE_URI", attr->values[0].string.text);
863 }
864
865 /*
866 * User needs to set the full URI...
867 */
868
869 cgiStartHTML(title);
870 cgiCopyTemplateLang("choose-uri.tmpl");
871 cgiEndHTML();
872 }
873 else if (!strncmp(var, "serial:", 7) && !cgiGetVariable("BAUDRATE"))
874 {
875 /*
876 * Need baud rate, parity, etc.
877 */
878
879 if ((var = strchr(var, '?')) != NULL &&
880 strncmp(var, "?baud=", 6) == 0)
881 maxrate = atoi(var + 6);
882 else
883 maxrate = 19200;
884
885 for (i = 0; i < 10; i ++)
886 if (baudrates[i] > maxrate)
887 break;
888 else
889 {
890 sprintf(baudrate, "%d", baudrates[i]);
891 cgiSetArray("BAUDRATES", i, baudrate);
892 }
893
894 cgiStartHTML(title);
895 cgiCopyTemplateLang("choose-serial.tmpl");
896 cgiEndHTML();
897 }
898 else if (!file && (var = cgiGetVariable("PPD_NAME")) == NULL)
899 {
900 if (modify)
901 {
902 /*
903 * Get the PPD file...
904 */
905
906 int fd; /* PPD file */
907 char filename[1024]; /* PPD filename */
908 ppd_file_t *ppd; /* PPD information */
909 char buffer[1024]; /* Buffer */
910 int bytes; /* Number of bytes */
911 http_status_t get_status; /* Status of GET */
912
913
a4d04587 914 /* TODO: Use cupsGetFile() API... */
ef416fc2 915 snprintf(uri, sizeof(uri), "/printers/%s.ppd", name);
916
917 if (httpGet(http, uri))
918 httpGet(http, uri);
919
920 while ((get_status = httpUpdate(http)) == HTTP_CONTINUE);
921
922 if (get_status != HTTP_OK)
923 {
924 fprintf(stderr, "ERROR: Unable to get PPD file %s: %d - %s\n",
925 uri, get_status, httpStatus(get_status));
926 }
927 else if ((fd = cupsTempFd(filename, sizeof(filename))) >= 0)
928 {
a4d04587 929 while ((bytes = httpRead2(http, buffer, sizeof(buffer))) > 0)
ef416fc2 930 write(fd, buffer, bytes);
931
932 close(fd);
933
934 if ((ppd = ppdOpenFile(filename)) != NULL)
935 {
936 if (ppd->manufacturer)
937 cgiSetVariable("CURRENT_MAKE", ppd->manufacturer);
938
939 if (ppd->nickname)
940 cgiSetVariable("CURRENT_MAKE_AND_MODEL", ppd->nickname);
941
942 ppdClose(ppd);
943 unlink(filename);
944 }
945 else
946 {
947 fprintf(stderr, "ERROR: Unable to open PPD file %s: %s\n",
948 filename, ppdErrorString(ppdLastError(&bytes)));
949 }
950 }
951 else
952 {
953 httpFlush(http);
954
955 fprintf(stderr,
956 "ERROR: Unable to create temporary file for PPD file: %s\n",
957 strerror(errno));
958 }
959 }
960 else if ((uriptr = strrchr(cgiGetVariable("DEVICE_URI"), '|')) != NULL)
961 {
962 /*
963 * Extract make and make/model from device URI string...
964 */
965
966 char make[1024], /* Make string */
967 *makeptr; /* Pointer into make */
968
969
970 *uriptr++ = '\0';
971
972 strlcpy(make, uriptr, sizeof(make));
973
974 if ((makeptr = strchr(make, ' ')) != NULL)
975 *makeptr = '\0';
976 else if ((makeptr = strchr(make, '-')) != NULL)
977 *makeptr = '\0';
978 else if (!strncasecmp(make, "laserjet", 8) ||
979 !strncasecmp(make, "deskjet", 7) ||
980 !strncasecmp(make, "designjet", 9))
981 strcpy(make, "HP");
982 else if (!strncasecmp(make, "phaser", 6))
983 strcpy(make, "Xerox");
984 else if (!strncasecmp(make, "stylus", 6))
985 strcpy(make, "Epson");
986 else
987 strcpy(make, "Generic");
988
989 cgiSetVariable("CURRENT_MAKE", make);
990 cgiSetVariable("PPD_MAKE", make);
991 cgiSetVariable("CURRENT_MAKE_AND_MODEL", uriptr);
992 }
993
994 /*
995 * Build a CUPS_GET_PPDS request, which requires the following
996 * attributes:
997 *
998 * attributes-charset
999 * attributes-natural-language
1000 * printer-uri
1001 */
1002
fa73b229 1003 request = ippNewRequest(CUPS_GET_PPDS);
ef416fc2 1004
1005 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
1006 NULL, "ipp://localhost/printers/");
1007
ef416fc2 1008 if ((var = cgiGetVariable("PPD_MAKE")) != NULL)
1009 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_TEXT,
1010 "ppd-make", NULL, var);
1011 else
1012 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
1013 "requested-attributes", NULL, "ppd-make");
1014
1015 /*
1016 * Do the request and get back a response...
1017 */
1018
1019 if ((response = cupsDoRequest(http, request, "/")) != NULL)
1020 {
1021 /*
1022 * Got the list of PPDs, see if the user has selected a make...
1023 */
1024
89d46774 1025 if (cgiSetIPPVars(response, NULL, NULL, NULL, 0) == 0)
ef416fc2 1026 {
1027 /*
89d46774 1028 * No PPD files with this make, try again with all makes...
ef416fc2 1029 */
1030
89d46774 1031 ippDelete(response);
1032
1033 request = ippNewRequest(CUPS_GET_PPDS);
1034
1035 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
1036 NULL, "ipp://localhost/printers/");
1037
1038 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
1039 "requested-attributes", NULL, "ppd-make");
ef416fc2 1040
89d46774 1041 if ((response = cupsDoRequest(http, request, "/")) != NULL)
1042 cgiSetIPPVars(response, NULL, NULL, NULL, 0);
1043
1044 cgiStartHTML(title);
1045 cgiCopyTemplateLang("choose-make.tmpl");
1046 cgiEndHTML();
1047 }
1048 else if (!var)
1049 {
ef416fc2 1050 cgiStartHTML(title);
1051 cgiCopyTemplateLang("choose-make.tmpl");
1052 cgiEndHTML();
1053 }
1054 else
1055 {
1056 /*
1057 * Let the user choose a model...
1058 */
1059
1060 const char *make_model; /* Current make/model string */
1061
1062
1063 if ((make_model = cgiGetVariable("CURRENT_MAKE_AND_MODEL")) != NULL)
1064 {
1065 /*
1066 * Scan for "close" matches...
1067 */
1068
1069 int match, /* Current match */
1070 best_match, /* Best match so far */
1071 count; /* Number of drivers */
1072 const char *best, /* Best matching string */
1073 *current; /* Current string */
1074
1075
1076 count = cgiGetSize("PPD_MAKE_AND_MODEL");
1077
1078 for (i = 0, best_match = 0, best = NULL; i < count; i ++)
1079 {
1080 current = cgiGetArray("PPD_MAKE_AND_MODEL", i);
1081 match = match_string(make_model, current);
1082
1083 if (match > best_match)
1084 {
1085 best_match = match;
1086 best = current;
1087 }
1088 }
1089
1090 if (best_match > strlen(var))
1091 {
1092 /*
1093 * Found a match longer than the make...
1094 */
1095
1096 cgiSetVariable("CURRENT_MAKE_AND_MODEL", best);
1097 }
1098 }
1099
1100 cgiStartHTML(title);
1101 cgiCopyTemplateLang("choose-model.tmpl");
1102 cgiEndHTML();
1103 }
1104
ef416fc2 1105 ippDelete(response);
1106 }
1107 else
1108 {
ef416fc2 1109 cgiStartHTML(title);
fa73b229 1110 cgiShowIPPError(_("Unable to get list of printer drivers:"));
ef416fc2 1111 cgiCopyTemplateLang("error.tmpl");
1112 cgiEndHTML();
1113 }
1114 }
1115 else
1116 {
1117 /*
1118 * Build a CUPS_ADD_PRINTER request, which requires the following
1119 * attributes:
1120 *
1121 * attributes-charset
1122 * attributes-natural-language
1123 * printer-uri
1124 * printer-location
1125 * printer-info
1126 * ppd-name
1127 * device-uri
1128 * printer-is-accepting-jobs
1129 * printer-state
1130 */
1131
fa73b229 1132 request = ippNewRequest(CUPS_ADD_PRINTER);
ef416fc2 1133
a4d04587 1134 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
1135 "localhost", 0, "/printers/%s",
1136 cgiGetVariable("PRINTER_NAME"));
ef416fc2 1137 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
1138 NULL, uri);
1139
1140 ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-location",
1141 NULL, cgiGetVariable("PRINTER_LOCATION"));
1142
1143 ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-info",
1144 NULL, cgiGetVariable("PRINTER_INFO"));
1145
1146 if (!file)
1147 ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_NAME, "ppd-name",
1148 NULL, cgiGetVariable("PPD_NAME"));
1149
1150 strlcpy(uri, cgiGetVariable("DEVICE_URI"), sizeof(uri));
1151
1152 /*
1153 * Strip make and model from URI...
1154 */
1155
1156 if ((uriptr = strrchr(uri, '|')) != NULL)
1157 *uriptr = '\0';
1158
fa73b229 1159 if (!strncmp(uri, "serial:", 7))
ef416fc2 1160 {
1161 /*
1162 * Update serial port URI to include baud rate, etc.
1163 */
1164
1165 if ((uriptr = strchr(uri, '?')) == NULL)
1166 uriptr = uri + strlen(uri);
1167
1168 snprintf(uriptr, sizeof(uri) - (uriptr - uri),
1169 "?baud=%s+bits=%s+parity=%s+flow=%s",
1170 cgiGetVariable("BAUDRATE"), cgiGetVariable("BITS"),
1171 cgiGetVariable("PARITY"), cgiGetVariable("FLOW"));
1172 }
1173
1174 ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_URI, "device-uri",
1175 NULL, uri);
1176
1177 ippAddBoolean(request, IPP_TAG_PRINTER, "printer-is-accepting-jobs", 1);
1178
1179 ippAddInteger(request, IPP_TAG_PRINTER, IPP_TAG_ENUM, "printer-state",
1180 IPP_PRINTER_IDLE);
1181
1182 /*
1183 * Do the request and get back a response...
1184 */
1185
1186 if (file)
fa73b229 1187 ippDelete(cupsDoFileRequest(http, request, "/admin/", file->tempfile));
ef416fc2 1188 else
fa73b229 1189 ippDelete(cupsDoRequest(http, request, "/admin/"));
ef416fc2 1190
fa73b229 1191 if (cupsLastError() > IPP_OK_CONFLICT)
ef416fc2 1192 {
1193 cgiStartHTML(title);
fa73b229 1194 cgiShowIPPError(modify ? _("Unable to modify printer:") :
1195 _("Unable to add printer:"));
ef416fc2 1196 }
1197 else
1198 {
1199 /*
1200 * Redirect successful updates back to the printer or set-options pages...
1201 */
1202
1203 char refresh[1024]; /* Refresh URL */
1204
1205
1206 cgiFormEncode(uri, name, sizeof(uri));
1207
1208 if (modify)
1209 snprintf(refresh, sizeof(refresh),
fa73b229 1210 "5;/admin/?OP=redirect&URL=/printers/%s", uri);
ef416fc2 1211 else
1212 snprintf(refresh, sizeof(refresh),
f301802f 1213 "5;URL=/admin/?OP=set-printer-options&PRINTER_NAME=%s", uri);
ef416fc2 1214
1215 cgiSetVariable("refresh_page", refresh);
1216
1217 cgiStartHTML(title);
1218
1219 if (modify)
1220 cgiCopyTemplateLang("printer-modified.tmpl");
1221 else
1222 cgiCopyTemplateLang("printer-added.tmpl");
1223 }
1224
1225 cgiEndHTML();
1226 }
1227
1228 if (oldinfo)
1229 ippDelete(oldinfo);
1230}
1231
1232
f7deaa1a 1233/*
1234 * 'do_cancel_subscription()' - Cancel a subscription.
1235 */
1236
1237static void
1238do_cancel_subscription(http_t *http)/* I - HTTP connection */
1239{
1240 ipp_t *request; /* IPP request data */
1241 const char *var, /* Form variable */
1242 *user; /* Username */
1243 int id; /* Subscription ID */
1244
1245
1246 /*
1247 * See if we have all of the required information...
1248 */
1249
1250 if ((var = cgiGetVariable("NOTIFY_SUBSCRIPTION_ID")) != NULL)
1251 id = atoi(var);
1252 else
1253 id = 0;
1254
1255 if (id <= 0)
1256 {
1257 cgiSetVariable("ERROR", cgiText(_("Bad subscription ID!")));
1258 cgiStartHTML(_("Cancel RSS Subscription"));
1259 cgiCopyTemplateLang("error.tmpl");
1260 cgiEndHTML();
1261 return;
1262 }
1263
1264 /*
1265 * Cancel the subscription...
1266 */
1267
1268 request = ippNewRequest(IPP_CANCEL_SUBSCRIPTION);
1269
1270 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
1271 NULL, "ipp://localhost/");
1272 ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_INTEGER,
1273 "notify-subscription-id", id);
1274
1275 if ((user = getenv("REMOTE_USER")) == NULL)
1276 user = "guest";
1277
1278 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
1279 NULL, user);
1280
1281 ippDelete(cupsDoRequest(http, request, "/"));
1282
1283 if (cupsLastError() > IPP_OK_CONFLICT)
1284 {
1285 cgiStartHTML(_("Cancel RSS Subscription"));
1286 cgiShowIPPError(_("Unable to cancel RSS subscription:"));
1287 }
1288 else
1289 {
1290 /*
1291 * Redirect successful updates back to the admin page...
1292 */
1293
1294 cgiSetVariable("refresh_page", "5;URL=/admin");
1295 cgiStartHTML(_("Cancel RSS Subscription"));
1296 cgiCopyTemplateLang("subscription-canceled.tmpl");
1297 }
1298
1299 cgiEndHTML();
1300}
1301
1302
ef416fc2 1303/*
323c5de1 1304 * 'do_config_server()' - Configure server settings.
ef416fc2 1305 */
1306
1307static void
323c5de1 1308do_config_server(http_t *http) /* I - HTTP connection */
ef416fc2 1309{
323c5de1 1310 if (cgiIsPOST() && !cgiGetVariable("CUPSDCONF"))
ef416fc2 1311 {
323c5de1 1312 /*
1313 * Save basic setting changes...
1314 */
ef416fc2 1315
323c5de1 1316 int num_settings; /* Number of server settings */
1317 cups_option_t *settings; /* Server settings */
1318 const char *debug_logging, /* DEBUG_LOGGING value */
1319 *remote_admin, /* REMOTE_ADMIN value */
1320 *remote_any, /* REMOTE_ANY value */
1321 *remote_printers,
1322 /* REMOTE_PRINTERS value */
1323 *share_printers,/* SHARE_PRINTERS value */
1324#ifdef HAVE_GSSAPI
1325 *default_auth_type,
1326 /* DefaultAuthType value */
1327#endif /* HAVE_GSSAPI */
1328 *user_cancel_any;
1329 /* USER_CANCEL_ANY value */
bd7854cb 1330
ef416fc2 1331
323c5de1 1332 /*
1333 * Get the checkbox values from the form...
1334 */
bd7854cb 1335
323c5de1 1336 debug_logging = cgiGetVariable("DEBUG_LOGGING") ? "1" : "0";
1337 remote_admin = cgiGetVariable("REMOTE_ADMIN") ? "1" : "0";
1338 remote_any = cgiGetVariable("REMOTE_ANY") ? "1" : "0";
1339 remote_printers = cgiGetVariable("REMOTE_PRINTERS") ? "1" : "0";
1340 share_printers = cgiGetVariable("SHARE_PRINTERS") ? "1" : "0";
1341 user_cancel_any = cgiGetVariable("USER_CANCEL_ANY") ? "1" : "0";
1342#ifdef HAVE_GSSAPI
1343 default_auth_type = cgiGetVariable("KERBEROS") ? "Negotiate" : "Basic";
ef416fc2 1344
323c5de1 1345 fprintf(stderr, "DEBUG: DefaultAuthType %s\n", default_auth_type);
1346#endif /* HAVE_GSSAPI */
bd7854cb 1347
323c5de1 1348 /*
1349 * Get the current server settings...
1350 */
ef416fc2 1351
323c5de1 1352 if (!cupsAdminGetServerSettings(http, &num_settings, &settings))
1353 {
1354 cgiStartHTML(cgiText(_("Change Settings")));
1355 cgiSetVariable("MESSAGE",
1356 cgiText(_("Unable to change server settings:")));
1357 cgiSetVariable("ERROR", cupsLastErrorString());
1358 cgiCopyTemplateLang("error.tmpl");
1359 cgiEndHTML();
1360 return;
1361 }
ef416fc2 1362
323c5de1 1363 /*
1364 * See if the settings have changed...
1365 */
1366
1367 if (strcmp(debug_logging, cupsGetOption(CUPS_SERVER_DEBUG_LOGGING,
1368 num_settings, settings)) ||
1369 strcmp(remote_admin, cupsGetOption(CUPS_SERVER_REMOTE_ADMIN,
1370 num_settings, settings)) ||
1371 strcmp(remote_any, cupsGetOption(CUPS_SERVER_REMOTE_ANY,
1372 num_settings, settings)) ||
1373 strcmp(remote_printers, cupsGetOption(CUPS_SERVER_REMOTE_PRINTERS,
1374 num_settings, settings)) ||
1375 strcmp(share_printers, cupsGetOption(CUPS_SERVER_SHARE_PRINTERS,
1376 num_settings, settings)) ||
1377#ifdef HAVE_GSSAPI
1378 !cupsGetOption("DefaultAuthType", num_settings, settings) ||
1379 strcmp(default_auth_type, cupsGetOption("DefaultAuthType",
1380 num_settings, settings)) ||
1381#endif /* HAVE_GSSAPI */
1382 strcmp(user_cancel_any, cupsGetOption(CUPS_SERVER_USER_CANCEL_ANY,
1383 num_settings, settings)))
1384 {
1385 /*
1386 * Settings *have* changed, so save the changes...
1387 */
ef416fc2 1388
323c5de1 1389 cupsFreeOptions(num_settings, settings);
ef416fc2 1390
323c5de1 1391 num_settings = 0;
1392 num_settings = cupsAddOption(CUPS_SERVER_DEBUG_LOGGING,
1393 debug_logging, num_settings, &settings);
1394 num_settings = cupsAddOption(CUPS_SERVER_REMOTE_ADMIN,
1395 remote_admin, num_settings, &settings);
1396 num_settings = cupsAddOption(CUPS_SERVER_REMOTE_ANY,
1397 remote_any, num_settings, &settings);
1398 num_settings = cupsAddOption(CUPS_SERVER_REMOTE_PRINTERS,
1399 remote_printers, num_settings, &settings);
1400 num_settings = cupsAddOption(CUPS_SERVER_SHARE_PRINTERS,
1401 share_printers, num_settings, &settings);
1402 num_settings = cupsAddOption(CUPS_SERVER_USER_CANCEL_ANY,
1403 user_cancel_any, num_settings, &settings);
1404#ifdef HAVE_GSSAPI
1405 num_settings = cupsAddOption("DefaultAuthType", default_auth_type,
1406 num_settings, &settings);
1407#endif /* HAVE_GSSAPI */
ef416fc2 1408
323c5de1 1409 if (!cupsAdminSetServerSettings(http, num_settings, settings))
ef416fc2 1410 {
323c5de1 1411 cgiStartHTML(cgiText(_("Change Settings")));
1412 cgiSetVariable("MESSAGE",
1413 cgiText(_("Unable to change server settings:")));
1414 cgiSetVariable("ERROR", cupsLastErrorString());
1415 cgiCopyTemplateLang("error.tmpl");
ef416fc2 1416 }
ef416fc2 1417 else
323c5de1 1418 {
1419 cgiSetVariable("refresh_page", "5;URL=/admin/?OP=redirect");
1420 cgiStartHTML(cgiText(_("Change Settings")));
1421 cgiCopyTemplateLang("restart.tmpl");
1422 }
1423 }
1424 else
1425 {
1426 /*
1427 * No changes...
1428 */
ef416fc2 1429
323c5de1 1430 cgiSetVariable("refresh_page", "5;URL=/admin/?OP=redirect");
1431 cgiStartHTML(cgiText(_("Change Settings")));
1432 cgiCopyTemplateLang("norestart.tmpl");
1433 }
ef416fc2 1434
323c5de1 1435 cupsFreeOptions(num_settings, settings);
ef416fc2 1436
323c5de1 1437 cgiEndHTML();
1438 }
1439 else if (cgiIsPOST())
ef416fc2 1440 {
1441 /*
323c5de1 1442 * Save hand-edited config file...
ef416fc2 1443 */
1444
323c5de1 1445 http_status_t status; /* PUT status */
1446 char tempfile[1024]; /* Temporary new cupsd.conf */
1447 int tempfd; /* Temporary file descriptor */
1448 cups_file_t *temp; /* Temporary file */
1449 const char *start, /* Start of line */
1450 *end; /* End of line */
bd7854cb 1451
fa73b229 1452
323c5de1 1453 /*
1454 * Create a temporary file for the new cupsd.conf file...
1455 */
ef416fc2 1456
323c5de1 1457 if ((tempfd = cupsTempFd(tempfile, sizeof(tempfile))) < 0)
ef416fc2 1458 {
323c5de1 1459 cgiStartHTML(cgiText(_("Edit Configuration File")));
1460 cgiSetVariable("MESSAGE", cgiText(_("Unable to create temporary file:")));
1461 cgiSetVariable("ERROR", strerror(errno));
1462 cgiCopyTemplateLang("error.tmpl");
1463 cgiEndHTML();
1464
1465 perror(tempfile);
1466 return;
ef416fc2 1467 }
1468
323c5de1 1469 if ((temp = cupsFileOpenFd(tempfd, "w")) == NULL)
ef416fc2 1470 {
323c5de1 1471 cgiStartHTML(cgiText(_("Edit Configuration File")));
1472 cgiSetVariable("MESSAGE", cgiText(_("Unable to create temporary file:")));
1473 cgiSetVariable("ERROR", strerror(errno));
1474 cgiCopyTemplateLang("error.tmpl");
1475 cgiEndHTML();
ef416fc2 1476
323c5de1 1477 perror(tempfile);
1478 close(tempfd);
1479 unlink(tempfile);
1480 return;
1481 }
ef416fc2 1482
323c5de1 1483 /*
1484 * Copy the cupsd.conf text from the form variable...
1485 */
ef416fc2 1486
323c5de1 1487 start = cgiGetVariable("CUPSDCONF");
1488 while (start)
1489 {
1490 if ((end = strstr(start, "\r\n")) == NULL)
1491 if ((end = strstr(start, "\n")) == NULL)
1492 end = start + strlen(start);
ef416fc2 1493
323c5de1 1494 cupsFileWrite(temp, start, end - start);
1495 cupsFilePutChar(temp, '\n');
ef416fc2 1496
323c5de1 1497 if (*end == '\r')
1498 start = end + 2;
1499 else if (*end == '\n')
1500 start = end + 1;
1501 else
1502 start = NULL;
1503 }
ef416fc2 1504
323c5de1 1505 cupsFileClose(temp);
ef416fc2 1506
323c5de1 1507 /*
1508 * Upload the configuration file to the server...
1509 */
ef416fc2 1510
323c5de1 1511 status = cupsPutFile(http, "/admin/conf/cupsd.conf", tempfile);
ef416fc2 1512
323c5de1 1513 if (status != HTTP_CREATED)
1514 {
1515 cgiSetVariable("MESSAGE",
1516 cgiText(_("Unable to upload cupsd.conf file:")));
1517 cgiSetVariable("ERROR", httpStatus(status));
1518
1519 cgiStartHTML(cgiText(_("Edit Configuration File")));
1520 cgiCopyTemplateLang("error.tmpl");
1521 }
1522 else
1523 {
1524 cgiSetVariable("refresh_page", "5;URL=/admin/?OP=redirect");
1525
1526 cgiStartHTML(cgiText(_("Edit Configuration File")));
1527 cgiCopyTemplateLang("restart.tmpl");
ef416fc2 1528 }
1529
323c5de1 1530 cgiEndHTML();
1531
1532 unlink(tempfile);
1533 }
1534 else
1535 {
1536 struct stat info; /* cupsd.conf information */
1537 cups_file_t *cupsd; /* cupsd.conf file */
1538 char *buffer; /* Buffer for entire file */
1539 char filename[1024]; /* Filename */
1540 const char *server_root; /* Location of config files */
1541
1542
ef416fc2 1543 /*
323c5de1 1544 * Locate the cupsd.conf file...
ef416fc2 1545 */
1546
323c5de1 1547 if ((server_root = getenv("CUPS_SERVERROOT")) == NULL)
1548 server_root = CUPS_SERVERROOT;
ef416fc2 1549
323c5de1 1550 snprintf(filename, sizeof(filename), "%s/cupsd.conf", server_root);
ef416fc2 1551
1552 /*
323c5de1 1553 * Figure out the size...
ef416fc2 1554 */
1555
323c5de1 1556 if (stat(filename, &info))
ef416fc2 1557 {
323c5de1 1558 cgiStartHTML(cgiText(_("Edit Configuration File")));
1559 cgiSetVariable("MESSAGE",
1560 cgiText(_("Unable to access cupsd.conf file:")));
1561 cgiSetVariable("ERROR", strerror(errno));
1562 cgiCopyTemplateLang("error.tmpl");
1563 cgiEndHTML();
ef416fc2 1564
323c5de1 1565 perror(filename);
1566 return;
1567 }
ef416fc2 1568
323c5de1 1569 if (info.st_size > (1024 * 1024))
1570 {
1571 cgiStartHTML(cgiText(_("Edit Configuration File")));
1572 cgiSetVariable("MESSAGE",
1573 cgiText(_("Unable to access cupsd.conf file:")));
1574 cgiSetVariable("ERROR",
1575 cgiText(_("Unable to edit cupsd.conf files larger than "
1576 "1MB!")));
1577 cgiCopyTemplateLang("error.tmpl");
1578 cgiEndHTML();
ef416fc2 1579
323c5de1 1580 fprintf(stderr, "ERROR: \"%s\" too large (%ld) to edit!\n", filename,
1581 (long)info.st_size);
1582 return;
1583 }
ef416fc2 1584
323c5de1 1585 /*
1586 * Open the cupsd.conf file...
1587 */
ef416fc2 1588
323c5de1 1589 if ((cupsd = cupsFileOpen(filename, "r")) == NULL)
1590 {
1591 /*
1592 * Unable to open - log an error...
1593 */
ef416fc2 1594
323c5de1 1595 cgiStartHTML(cgiText(_("Edit Configuration File")));
1596 cgiSetVariable("MESSAGE",
1597 cgiText(_("Unable to access cupsd.conf file:")));
1598 cgiSetVariable("ERROR", strerror(errno));
1599 cgiCopyTemplateLang("error.tmpl");
1600 cgiEndHTML();
ef416fc2 1601
323c5de1 1602 perror(filename);
1603 return;
1604 }
ef416fc2 1605
323c5de1 1606 /*
1607 * Allocate memory and load the file into a string buffer...
1608 */
ef416fc2 1609
323c5de1 1610 buffer = calloc(1, info.st_size + 1);
ef416fc2 1611
323c5de1 1612 cupsFileRead(cupsd, buffer, info.st_size);
1613 cupsFileClose(cupsd);
ef416fc2 1614
323c5de1 1615 cgiSetVariable("CUPSDCONF", buffer);
1616 free(buffer);
ef416fc2 1617
323c5de1 1618 /*
1619 * Show the current config file...
1620 */
ef416fc2 1621
323c5de1 1622 cgiStartHTML(cgiText(_("Edit Configuration File")));
ef416fc2 1623
323c5de1 1624 printf("<!-- \"%s\" -->\n", filename);
ef416fc2 1625
323c5de1 1626 cgiCopyTemplateLang("edit-config.tmpl");
ef416fc2 1627
323c5de1 1628 cgiEndHTML();
1629 }
1630}
ef416fc2 1631
ef416fc2 1632
323c5de1 1633/*
1634 * 'do_delete_class()' - Delete a class...
1635 */
ef416fc2 1636
323c5de1 1637static void
1638do_delete_class(http_t *http) /* I - HTTP connection */
1639{
1640 ipp_t *request; /* IPP request */
1641 char uri[HTTP_MAX_URI]; /* Job URI */
1642 const char *pclass; /* Printer class name */
ef416fc2 1643
ef416fc2 1644
323c5de1 1645 /*
1646 * Get form variables...
1647 */
ef416fc2 1648
323c5de1 1649 if (cgiGetVariable("CONFIRM") == NULL)
1650 {
1651 cgiStartHTML(cgiText(_("Delete Class")));
1652 cgiCopyTemplateLang("class-confirm.tmpl");
1653 cgiEndHTML();
1654 return;
1655 }
ef416fc2 1656
323c5de1 1657 if ((pclass = cgiGetVariable("PRINTER_NAME")) != NULL)
1658 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
1659 "localhost", 0, "/classes/%s", pclass);
1660 else
1661 {
1662 cgiStartHTML(cgiText(_("Delete Class")));
1663 cgiSetVariable("ERROR", cgiText(_("Missing form variable!")));
1664 cgiCopyTemplateLang("error.tmpl");
1665 cgiEndHTML();
1666 return;
1667 }
ef416fc2 1668
323c5de1 1669 /*
1670 * Build a CUPS_DELETE_CLASS request, which requires the following
1671 * attributes:
1672 *
1673 * attributes-charset
1674 * attributes-natural-language
1675 * printer-uri
1676 */
1677
1678 request = ippNewRequest(CUPS_DELETE_CLASS);
1679
1680 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
1681 NULL, uri);
1682
1683 /*
1684 * Do the request and get back a response...
1685 */
1686
1687 ippDelete(cupsDoRequest(http, request, "/admin/"));
ef416fc2 1688
323c5de1 1689 /*
1690 * Show the results...
1691 */
1692
1693 if (cupsLastError() <= IPP_OK_CONFLICT)
1694 {
ef416fc2 1695 /*
323c5de1 1696 * Redirect successful updates back to the classes page...
ef416fc2 1697 */
1698
323c5de1 1699 cgiSetVariable("refresh_page", "5;URL=/admin/?OP=redirect&URL=/classes");
1700 }
ef416fc2 1701
323c5de1 1702 cgiStartHTML(cgiText(_("Delete Class")));
ef416fc2 1703
323c5de1 1704 if (cupsLastError() > IPP_OK_CONFLICT)
1705 cgiShowIPPError(_("Unable to delete class:"));
1706 else
1707 cgiCopyTemplateLang("class-deleted.tmpl");
ef416fc2 1708
323c5de1 1709 cgiEndHTML();
1710}
ef416fc2 1711
ef416fc2 1712
323c5de1 1713/*
1714 * 'do_delete_printer()' - Delete a printer...
1715 */
ef416fc2 1716
323c5de1 1717static void
1718do_delete_printer(http_t *http) /* I - HTTP connection */
1719{
1720 ipp_t *request; /* IPP request */
1721 char uri[HTTP_MAX_URI]; /* Job URI */
1722 const char *printer; /* Printer printer name */
ef416fc2 1723
323c5de1 1724
1725 /*
1726 * Get form variables...
1727 */
1728
1729 if (cgiGetVariable("CONFIRM") == NULL)
1730 {
1731 cgiStartHTML(cgiText(_("Delete Printer")));
1732 cgiCopyTemplateLang("printer-confirm.tmpl");
ef416fc2 1733 cgiEndHTML();
323c5de1 1734 return;
ef416fc2 1735 }
323c5de1 1736
1737 if ((printer = cgiGetVariable("PRINTER_NAME")) != NULL)
1738 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
1739 "localhost", 0, "/printers/%s", printer);
ef416fc2 1740 else
323c5de1 1741 {
1742 cgiStartHTML(cgiText(_("Delete Printer")));
1743 cgiSetVariable("ERROR", cgiText(_("Missing form variable!")));
1744 cgiCopyTemplateLang("error.tmpl");
1745 cgiEndHTML();
1746 return;
1747 }
1748
1749 /*
1750 * Build a CUPS_DELETE_PRINTER request, which requires the following
1751 * attributes:
1752 *
1753 * attributes-charset
1754 * attributes-natural-language
1755 * printer-uri
1756 */
1757
1758 request = ippNewRequest(CUPS_DELETE_PRINTER);
1759
1760 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
1761 NULL, uri);
1762
1763 /*
1764 * Do the request and get back a response...
1765 */
1766
1767 ippDelete(cupsDoRequest(http, request, "/admin/"));
1768
1769 /*
1770 * Show the results...
1771 */
1772
1773 if (cupsLastError() <= IPP_OK_CONFLICT)
ef416fc2 1774 {
1775 /*
323c5de1 1776 * Redirect successful updates back to the printers page...
ef416fc2 1777 */
1778
323c5de1 1779 cgiSetVariable("refresh_page", "5;URL=/admin/?OP=redirect&URL=/printers");
1780 }
bd7854cb 1781
323c5de1 1782 cgiStartHTML(cgiText(_("Delete Printer")));
ef416fc2 1783
323c5de1 1784 if (cupsLastError() > IPP_OK_CONFLICT)
1785 cgiShowIPPError(_("Unable to delete printer:"));
1786 else
1787 cgiCopyTemplateLang("printer-deleted.tmpl");
ef416fc2 1788
323c5de1 1789 cgiEndHTML();
1790}
ef416fc2 1791
ef416fc2 1792
323c5de1 1793/*
1794 * 'do_export()' - Export printers to Samba...
1795 */
ef416fc2 1796
323c5de1 1797static void
1798do_export(http_t *http) /* I - HTTP connection */
1799{
1800 int i, j; /* Looping vars */
1801 ipp_t *request, /* IPP request */
1802 *response; /* IPP response */
1803 const char *username, /* Samba username */
1804 *password, /* Samba password */
1805 *export_all; /* Export all printers? */
1806 int export_count, /* Number of printers to export */
1807 printer_count; /* Number of available printers */
1808 const char *name, /* What name to pull */
1809 *dest; /* Current destination */
1810 char ppd[1024]; /* PPD file */
ef416fc2 1811
ef416fc2 1812
323c5de1 1813 /*
1814 * Get form data...
1815 */
ef416fc2 1816
323c5de1 1817 username = cgiGetVariable("USERNAME");
1818 password = cgiGetVariable("PASSWORD");
1819 export_all = cgiGetVariable("EXPORT_ALL");
1820 export_count = cgiGetSize("EXPORT_NAME");
ef416fc2 1821
323c5de1 1822 /*
1823 * Get list of available printers...
1824 */
ef416fc2 1825
323c5de1 1826 cgiSetSize("PRINTER_NAME", 0);
1827 cgiSetSize("PRINTER_EXPORT", 0);
ef416fc2 1828
323c5de1 1829 request = ippNewRequest(CUPS_GET_PRINTERS);
ef416fc2 1830
323c5de1 1831 ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_ENUM,
1832 "printer-type", 0);
ef416fc2 1833
323c5de1 1834 ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_ENUM,
1835 "printer-type-mask", CUPS_PRINTER_CLASS | CUPS_PRINTER_REMOTE |
1836 CUPS_PRINTER_IMPLICIT);
ef416fc2 1837
323c5de1 1838 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
1839 "requested-attributes", NULL, "printer-name");
ef416fc2 1840
323c5de1 1841 if ((response = cupsDoRequest(http, request, "/")) != NULL)
1842 {
1843 cgiSetIPPVars(response, NULL, NULL, NULL, 0);
1844 ippDelete(response);
ef416fc2 1845
323c5de1 1846 if (!export_all)
1847 {
1848 printer_count = cgiGetSize("PRINTER_NAME");
ef416fc2 1849
323c5de1 1850 for (i = 0; i < printer_count; i ++)
1851 {
1852 dest = cgiGetArray("PRINTER_NAME", i);
ef416fc2 1853
323c5de1 1854 for (j = 0; j < export_count; j ++)
1855 if (!strcasecmp(dest, cgiGetArray("EXPORT_NAME", j)))
1856 break;
1857
1858 cgiSetArray("PRINTER_EXPORT", i, j < export_count ? "Y" : "");
1859 }
1860 }
1861 }
1862
1863 /*
1864 * Export or get the printers to export...
1865 */
ef416fc2 1866
323c5de1 1867 if (username && *username && password && *password &&
1868 (export_all || export_count > 0))
1869 {
ef416fc2 1870 /*
323c5de1 1871 * Do export...
ef416fc2 1872 */
1873
323c5de1 1874 fputs("DEBUG: Export printers...\n", stderr);
ef416fc2 1875
323c5de1 1876 if (export_all)
ef416fc2 1877 {
323c5de1 1878 name = "PRINTER_NAME";
1879 export_count = cgiGetSize("PRINTER_NAME");
ef416fc2 1880 }
1881 else
323c5de1 1882 name = "EXPORT_NAME";
ef416fc2 1883
323c5de1 1884 for (i = 0; i < export_count; i ++)
1885 {
1886 dest = cgiGetArray(name, i);
ef416fc2 1887
323c5de1 1888 if (!cupsAdminCreateWindowsPPD(http, dest, ppd, sizeof(ppd)))
1889 break;
fa73b229 1890
323c5de1 1891 j = cupsAdminExportSamba(dest, ppd, "localhost", username, password,
1892 stderr);
ef416fc2 1893
323c5de1 1894 unlink(ppd);
ef416fc2 1895
323c5de1 1896 if (!j)
1897 break;
ef416fc2 1898 }
1899
323c5de1 1900 if (i < export_count)
1901 cgiSetVariable("ERROR", cupsLastErrorString());
1902 else
1903 {
1904 cgiStartHTML(cgiText(_("Export Printers to Samba")));
1905 cgiCopyTemplateLang("samba-exported.tmpl");
1906 cgiEndHTML();
1907 return;
1908 }
ef416fc2 1909 }
323c5de1 1910 else if (username && !*username)
1911 cgiSetVariable("ERROR",
1912 cgiText(_("A Samba username is required to export "
1913 "printer drivers!")));
1914 else if (username && (!password || !*password))
1915 cgiSetVariable("ERROR",
1916 cgiText(_("A Samba password is required to export "
1917 "printer drivers!")));
1918
1919 /*
1920 * Show form...
1921 */
ef416fc2 1922
323c5de1 1923 cgiStartHTML(cgiText(_("Export Printers to Samba")));
1924 cgiCopyTemplateLang("samba-export.tmpl");
1925 cgiEndHTML();
ef416fc2 1926}
1927
1928
1929/*
323c5de1 1930 * 'do_list_printers()' - List available printers...
ef416fc2 1931 */
1932
1933static void
323c5de1 1934do_list_printers(http_t *http) /* I - HTTP connection */
ef416fc2 1935{
323c5de1 1936 ipp_t *request, /* IPP request */
1937 *response; /* IPP response */
1938 ipp_attribute_t *attr; /* IPP attribute */
ef416fc2 1939
757d2cad 1940
323c5de1 1941 cgiStartHTML(cgiText(_("List Available Printers")));
1942 fflush(stdout);
1943
1944 /*
1945 * Get the list of printers and their devices...
1946 */
1947
1948 request = ippNewRequest(CUPS_GET_PRINTERS);
1949
1950 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
1951 "requested-attributes", NULL, "device-uri");
1952
1953 ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_ENUM, "printer-type",
1954 CUPS_PRINTER_LOCAL);
1955 ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_ENUM, "printer-type-mask",
1956 CUPS_PRINTER_LOCAL);
757d2cad 1957
323c5de1 1958 if ((response = cupsDoRequest(http, request, "/")) != NULL)
1959 {
d09495fa 1960 /*
323c5de1 1961 * Got the printer list, now load the devices...
d09495fa 1962 */
1963
323c5de1 1964 int i; /* Looping var */
1965 cups_array_t *printer_devices; /* Printer devices for local printers */
1966 char *printer_device; /* Current printer device */
7594b224 1967
d09495fa 1968
1969 /*
323c5de1 1970 * Allocate an array and copy the device strings...
d09495fa 1971 */
1972
323c5de1 1973 printer_devices = cupsArrayNew((cups_array_func_t)strcmp, NULL);
1974
1975 for (attr = ippFindAttribute(response, "device-uri", IPP_TAG_URI);
1976 attr;
1977 attr = ippFindNextAttribute(response, "device-uri", IPP_TAG_URI))
ef416fc2 1978 {
323c5de1 1979 cupsArrayAdd(printer_devices, strdup(attr->values[0].string.text));
d09495fa 1980 }
1981
1982 /*
323c5de1 1983 * Free the printer list and get the device list...
d09495fa 1984 */
1985
323c5de1 1986 ippDelete(response);
d09495fa 1987
323c5de1 1988 request = ippNewRequest(CUPS_GET_DEVICES);
d09495fa 1989
323c5de1 1990 if ((response = cupsDoRequest(http, request, "/")) != NULL)
ef416fc2 1991 {
d09495fa 1992 /*
323c5de1 1993 * Got the device list, let's parse it...
d09495fa 1994 */
1995
323c5de1 1996 const char *device_uri, /* device-uri attribute value */
1997 *device_make_and_model, /* device-make-and-model value */
1998 *device_info; /* device-info value */
ef416fc2 1999
ef416fc2 2000
323c5de1 2001 for (i = 0, attr = response->attrs; attr; attr = attr->next)
2002 {
2003 /*
2004 * Skip leading attributes until we hit a device...
2005 */
ef416fc2 2006
323c5de1 2007 while (attr && attr->group_tag != IPP_TAG_PRINTER)
2008 attr = attr->next;
ef416fc2 2009
323c5de1 2010 if (!attr)
2011 break;
ef416fc2 2012
323c5de1 2013 /*
2014 * Pull the needed attributes from this device...
2015 */
ef416fc2 2016
323c5de1 2017 device_info = NULL;
2018 device_make_and_model = NULL;
2019 device_uri = NULL;
ef416fc2 2020
323c5de1 2021 while (attr && attr->group_tag == IPP_TAG_PRINTER)
2022 {
2023 if (!strcmp(attr->name, "device-info") &&
2024 attr->value_tag == IPP_TAG_TEXT)
2025 device_info = attr->values[0].string.text;
ef416fc2 2026
323c5de1 2027 if (!strcmp(attr->name, "device-make-and-model") &&
2028 attr->value_tag == IPP_TAG_TEXT)
2029 device_make_and_model = attr->values[0].string.text;
ef416fc2 2030
323c5de1 2031 if (!strcmp(attr->name, "device-uri") &&
2032 attr->value_tag == IPP_TAG_URI)
2033 device_uri = attr->values[0].string.text;
ef416fc2 2034
323c5de1 2035 attr = attr->next;
2036 }
ef416fc2 2037
323c5de1 2038 /*
2039 * See if we have everything needed...
2040 */
ef416fc2 2041
323c5de1 2042 if (device_info && device_make_and_model && device_uri &&
2043 strcasecmp(device_make_and_model, "unknown") &&
2044 strchr(device_uri, ':'))
2045 {
2046 /*
2047 * Yes, now see if there is already a printer for this
2048 * device...
2049 */
ef416fc2 2050
323c5de1 2051 if (!cupsArrayFind(printer_devices, (void *)device_uri))
2052 {
2053 /*
2054 * Not found, so it must be a new printer...
2055 */
ef416fc2 2056
323c5de1 2057 char options[1024], /* Form variables for this device */
2058 *options_ptr; /* Pointer into string */
2059 const char *ptr; /* Pointer into device string */
ef416fc2 2060
fa73b229 2061
323c5de1 2062 /*
2063 * Format the printer name variable for this device...
2064 *
2065 * We use the device-info string first, then device-uri,
2066 * and finally device-make-and-model to come up with a
2067 * suitable name.
2068 */
ef416fc2 2069
323c5de1 2070 strcpy(options, "TEMPLATE_NAME=");
2071 options_ptr = options + strlen(options);
ef416fc2 2072
323c5de1 2073 if (strncasecmp(device_info, "unknown", 7))
2074 ptr = device_info;
2075 else if ((ptr = strstr(device_uri, "://")) != NULL)
2076 ptr += 3;
2077 else
2078 ptr = device_make_and_model;
ef416fc2 2079
323c5de1 2080 for (;
2081 options_ptr < (options + sizeof(options) - 1) && *ptr;
2082 ptr ++)
2083 if (isalnum(*ptr & 255) || *ptr == '_' || *ptr == '-' ||
2084 *ptr == '.')
2085 *options_ptr++ = *ptr;
2086 else if ((*ptr == ' ' || *ptr == '/') && options_ptr[-1] != '_')
2087 *options_ptr++ = '_';
2088 else if (*ptr == '?' || *ptr == '(')
2089 break;
ef416fc2 2090
323c5de1 2091 /*
2092 * Then add the make and model in the printer info, so
2093 * that MacOS clients see something reasonable...
2094 */
ef416fc2 2095
323c5de1 2096 strlcpy(options_ptr, "&PRINTER_LOCATION=Local+Printer"
2097 "&PRINTER_INFO=",
2098 sizeof(options) - (options_ptr - options));
2099 options_ptr += strlen(options_ptr);
ef416fc2 2100
323c5de1 2101 cgiFormEncode(options_ptr, device_make_and_model,
2102 sizeof(options) - (options_ptr - options));
2103 options_ptr += strlen(options_ptr);
ef416fc2 2104
323c5de1 2105 /*
2106 * Then copy the device URI...
2107 */
ef416fc2 2108
323c5de1 2109 strlcpy(options_ptr, "&DEVICE_URI=",
2110 sizeof(options) - (options_ptr - options));
2111 options_ptr += strlen(options_ptr);
ef416fc2 2112
323c5de1 2113 cgiFormEncode(options_ptr, device_uri,
2114 sizeof(options) - (options_ptr - options));
2115 options_ptr += strlen(options_ptr);
ef416fc2 2116
323c5de1 2117 if (options_ptr < (options + sizeof(options) - 1))
2118 {
2119 *options_ptr++ = '|';
2120 cgiFormEncode(options_ptr, device_make_and_model,
2121 sizeof(options) - (options_ptr - options));
2122 }
ef416fc2 2123
323c5de1 2124 /*
2125 * Finally, set the form variables for this printer...
2126 */
ef416fc2 2127
323c5de1 2128 cgiSetArray("device_info", i, device_info);
2129 cgiSetArray("device_make_and_model", i, device_make_and_model);
2130 cgiSetArray("device_options", i, options);
2131 cgiSetArray("device_uri", i, device_uri);
2132 i ++;
2133 }
2134 }
ef416fc2 2135
323c5de1 2136 if (!attr)
2137 break;
2138 }
2139
2140 ippDelete(response);
ef416fc2 2141
ef416fc2 2142 /*
323c5de1 2143 * Free the device list...
ef416fc2 2144 */
2145
323c5de1 2146 for (printer_device = (char *)cupsArrayFirst(printer_devices);
2147 printer_device;
2148 printer_device = (char *)cupsArrayNext(printer_devices))
2149 free(printer_device);
ef416fc2 2150
323c5de1 2151 cupsArrayDelete(printer_devices);
ef416fc2 2152 }
323c5de1 2153 }
ef416fc2 2154
323c5de1 2155 /*
2156 * Finally, show the printer list...
2157 */
ef416fc2 2158
323c5de1 2159 cgiCopyTemplateLang("list-available-printers.tmpl");
ef416fc2 2160
323c5de1 2161 cgiEndHTML();
ef416fc2 2162}
2163
2164
2165/*
323c5de1 2166 * 'do_menu()' - Show the main menu...
ef416fc2 2167 */
2168
2169static void
323c5de1 2170do_menu(http_t *http) /* I - HTTP connection */
ef416fc2 2171{
323c5de1 2172 int num_settings; /* Number of server settings */
2173 cups_option_t *settings; /* Server settings */
2174 const char *val; /* Setting value */
2175 char filename[1024]; /* Temporary filename */
2176 const char *datadir; /* Location of data files */
2177 ipp_t *request, /* IPP request */
2178 *response; /* IPP response */
ef416fc2 2179
2180
89d46774 2181 /*
323c5de1 2182 * Get the current server settings...
89d46774 2183 */
fa73b229 2184
323c5de1 2185 if (!cupsAdminGetServerSettings(http, &num_settings, &settings))
ef416fc2 2186 {
323c5de1 2187 cgiSetVariable("SETTINGS_MESSAGE",
2188 cgiText(_("Unable to open cupsd.conf file:")));
2189 cgiSetVariable("SETTINGS_ERROR", cupsLastErrorString());
ef416fc2 2190 }
2191
323c5de1 2192 if ((val = cupsGetOption(CUPS_SERVER_DEBUG_LOGGING, num_settings,
2193 settings)) != NULL && atoi(val))
2194 cgiSetVariable("DEBUG_LOGGING", "CHECKED");
ef416fc2 2195
323c5de1 2196 if ((val = cupsGetOption(CUPS_SERVER_REMOTE_ADMIN, num_settings,
2197 settings)) != NULL && atoi(val))
2198 cgiSetVariable("REMOTE_ADMIN", "CHECKED");
ef416fc2 2199
323c5de1 2200 if ((val = cupsGetOption(CUPS_SERVER_REMOTE_ANY, num_settings,
2201 settings)) != NULL && atoi(val))
2202 cgiSetVariable("REMOTE_ANY", "CHECKED");
ef416fc2 2203
323c5de1 2204 if ((val = cupsGetOption(CUPS_SERVER_REMOTE_PRINTERS, num_settings,
2205 settings)) != NULL && atoi(val))
2206 cgiSetVariable("REMOTE_PRINTERS", "CHECKED");
ef416fc2 2207
323c5de1 2208 if ((val = cupsGetOption(CUPS_SERVER_SHARE_PRINTERS, num_settings,
2209 settings)) != NULL && atoi(val))
2210 cgiSetVariable("SHARE_PRINTERS", "CHECKED");
ef416fc2 2211
323c5de1 2212 if ((val = cupsGetOption(CUPS_SERVER_USER_CANCEL_ANY, num_settings,
2213 settings)) != NULL && atoi(val))
2214 cgiSetVariable("USER_CANCEL_ANY", "CHECKED");
2215
2216#ifdef HAVE_GSSAPI
2217 cgiSetVariable("HAVE_GSSAPI", "1");
2218
2219 if ((val = cupsGetOption("DefaultAuthType", num_settings,
2220 settings)) != NULL && !strcasecmp(val, "Negotiate"))
2221 cgiSetVariable("KERBEROS", "CHECKED");
2222#endif /* HAVE_GSSAPI */
2223
2224 cupsFreeOptions(num_settings, settings);
ef416fc2 2225
89d46774 2226 /*
323c5de1 2227 * See if Samba and the Windows drivers are installed...
89d46774 2228 */
2229
323c5de1 2230 if ((datadir = getenv("CUPS_DATADIR")) == NULL)
2231 datadir = CUPS_DATADIR;
2232
2233 snprintf(filename, sizeof(filename), "%s/drivers/pscript5.dll", datadir);
2234 if (!access(filename, R_OK))
f7deaa1a 2235 {
2236 /*
323c5de1 2237 * Found Windows 2000 driver file, see if we have smbclient and
2238 * rpcclient...
f7deaa1a 2239 */
2240
323c5de1 2241 if (cupsFileFind("smbclient", getenv("PATH"), 1, filename,
2242 sizeof(filename)) &&
2243 cupsFileFind("rpcclient", getenv("PATH"), 1, filename,
2244 sizeof(filename)))
2245 cgiSetVariable("HAVE_SAMBA", "Y");
2246 else
2247 {
2248 if (!cupsFileFind("smbclient", getenv("PATH"), 1, filename,
2249 sizeof(filename)))
2250 fputs("ERROR: smbclient not found!\n", stderr);
2251
2252 if (!cupsFileFind("rpcclient", getenv("PATH"), 1, filename,
2253 sizeof(filename)))
2254 fputs("ERROR: rpcclient not found!\n", stderr);
2255 }
f7deaa1a 2256 }
323c5de1 2257 else
2258 perror(filename);
f7deaa1a 2259
323c5de1 2260 /*
2261 * Subscriptions...
2262 */
89d46774 2263
323c5de1 2264 request = ippNewRequest(IPP_GET_SUBSCRIPTIONS);
2265
2266 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
2267 NULL, "ipp://localhost/");
2268
2269 if ((response = cupsDoRequest(http, request, "/")) != NULL)
2270 {
2271 cgiSetIPPVars(response, NULL, NULL, NULL, 0);
2272 ippDelete(response);
2273 }
2274
2275 /*
2276 * Finally, show the main menu template...
2277 */
2278
2279 cgiStartHTML(cgiText(_("Administration")));
2280
2281 cgiCopyTemplateLang("admin.tmpl");
ef416fc2 2282
2283 cgiEndHTML();
2284}
2285
2286
2287/*
323c5de1 2288 * 'do_printer_op()' - Do a printer operation.
ef416fc2 2289 */
2290
2291static void
323c5de1 2292do_printer_op(http_t *http, /* I - HTTP connection */
2293 ipp_op_t op, /* I - Operation to perform */
2294 const char *title) /* I - Title of page */
ef416fc2 2295{
fa73b229 2296 ipp_t *request; /* IPP request */
323c5de1 2297 char uri[HTTP_MAX_URI]; /* Printer URI */
2298 const char *printer, /* Printer name (purge-jobs) */
2299 *is_class; /* Is a class? */
ef416fc2 2300
fa73b229 2301
323c5de1 2302 is_class = cgiGetVariable("IS_CLASS");
2303 printer = cgiGetVariable("PRINTER_NAME");
ef416fc2 2304
323c5de1 2305 if (!printer)
ef416fc2 2306 {
fa73b229 2307 cgiSetVariable("ERROR", cgiText(_("Missing form variable!")));
323c5de1 2308 cgiStartHTML(title);
ef416fc2 2309 cgiCopyTemplateLang("error.tmpl");
2310 cgiEndHTML();
2311 return;
2312 }
2313
2314 /*
323c5de1 2315 * Build a printer request, which requires the following
ef416fc2 2316 * attributes:
2317 *
2318 * attributes-charset
2319 * attributes-natural-language
2320 * printer-uri
2321 */
2322
323c5de1 2323 request = ippNewRequest(op);
ef416fc2 2324
323c5de1 2325 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
2326 "localhost", 0, is_class ? "/classes/%s" : "/printers/%s",
2327 printer);
ef416fc2 2328 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
2329 NULL, uri);
2330
2331 /*
2332 * Do the request and get back a response...
2333 */
2334
fa73b229 2335 ippDelete(cupsDoRequest(http, request, "/admin/"));
2336
323c5de1 2337 if (cupsLastError() > IPP_OK_CONFLICT)
2338 {
2339 cgiStartHTML(title);
2340 cgiShowIPPError(_("Unable to change printer:"));
2341 }
2342 else
f7deaa1a 2343 {
2344 /*
323c5de1 2345 * Redirect successful updates back to the printer page...
f7deaa1a 2346 */
2347
323c5de1 2348 char url[1024], /* Printer/class URL */
2349 refresh[1024]; /* Refresh URL */
f7deaa1a 2350
89d46774 2351
323c5de1 2352 cgiRewriteURL(uri, url, sizeof(url), NULL);
2353 cgiFormEncode(uri, url, sizeof(uri));
2354 snprintf(refresh, sizeof(refresh), "5;URL=/admin/?OP=redirect&URL=%s", uri);
2355 cgiSetVariable("refresh_page", refresh);
2356
2357 cgiStartHTML(title);
2358
2359 if (op == IPP_PAUSE_PRINTER)
2360 cgiCopyTemplateLang("printer-stop.tmpl");
2361 else if (op == IPP_RESUME_PRINTER)
2362 cgiCopyTemplateLang("printer-start.tmpl");
2363 else if (op == CUPS_ACCEPT_JOBS)
2364 cgiCopyTemplateLang("printer-accept.tmpl");
2365 else if (op == CUPS_REJECT_JOBS)
2366 cgiCopyTemplateLang("printer-reject.tmpl");
2367 else if (op == IPP_PURGE_JOBS)
2368 cgiCopyTemplateLang("printer-purge.tmpl");
2369 else if (op == CUPS_SET_DEFAULT)
2370 cgiCopyTemplateLang("printer-default.tmpl");
2371 }
fa73b229 2372
2373 cgiEndHTML();
2374}
2375
2376
2377/*
323c5de1 2378 * 'do_set_allowed_users()' - Set the allowed/denied users for a queue.
fa73b229 2379 */
2380
2381static void
323c5de1 2382do_set_allowed_users(http_t *http) /* I - HTTP connection */
fa73b229 2383{
323c5de1 2384 int i; /* Looping var */
fa73b229 2385 ipp_t *request, /* IPP request */
2386 *response; /* IPP response */
323c5de1 2387 char uri[HTTP_MAX_URI]; /* Printer URI */
2388 const char *printer, /* Printer name (purge-jobs) */
2389 *is_class, /* Is a class? */
2390 *users, /* List of users or groups */
2391 *type; /* Allow/deny type */
2392 int num_users; /* Number of users */
2393 char *ptr, /* Pointer into users string */
2394 *end, /* Pointer to end of users string */
2395 quote; /* Quote character */
2396 ipp_attribute_t *attr; /* Attribute */
2397 static const char * const attrs[] = /* Requested attributes */
2398 {
2399 "requesting-user-name-allowed",
2400 "requesting-user-name-denied"
2401 };
fa73b229 2402
fa73b229 2403
323c5de1 2404 is_class = cgiGetVariable("IS_CLASS");
2405 printer = cgiGetVariable("PRINTER_NAME");
fa73b229 2406
323c5de1 2407 if (!printer)
2408 {
2409 cgiSetVariable("ERROR", cgiText(_("Missing form variable!")));
2410 cgiStartHTML(cgiText(_("Set Allowed Users")));
2411 cgiCopyTemplateLang("error.tmpl");
2412 cgiEndHTML();
2413 return;
2414 }
ef416fc2 2415
323c5de1 2416 users = cgiGetVariable("users");
2417 type = cgiGetVariable("type");
ef416fc2 2418
323c5de1 2419 if (!users || !type ||
2420 (strcmp(type, "requesting-user-name-allowed") &&
2421 strcmp(type, "requesting-user-name-denied")))
2422 {
2423 /*
2424 * Build a Get-Printer-Attributes request, which requires the following
2425 * attributes:
2426 *
2427 * attributes-charset
2428 * attributes-natural-language
2429 * printer-uri
2430 * requested-attributes
2431 */
fa73b229 2432
323c5de1 2433 request = ippNewRequest(IPP_GET_PRINTER_ATTRIBUTES);
fa73b229 2434
323c5de1 2435 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
2436 "localhost", 0, is_class ? "/classes/%s" : "/printers/%s",
2437 printer);
2438 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
2439 NULL, uri);
fa73b229 2440
323c5de1 2441 ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
2442 "requested-attributes",
2443 (int)(sizeof(attrs) / sizeof(attrs[0])), NULL, attrs);
fa73b229 2444
323c5de1 2445 /*
2446 * Do the request and get back a response...
2447 */
fa73b229 2448
323c5de1 2449 if ((response = cupsDoRequest(http, request, "/")) != NULL)
fa73b229 2450 {
323c5de1 2451 cgiSetIPPVars(response, NULL, NULL, NULL, 0);
fa73b229 2452
323c5de1 2453 ippDelete(response);
fa73b229 2454 }
ef416fc2 2455
323c5de1 2456 cgiStartHTML(cgiText(_("Set Allowed Users")));
757d2cad 2457
323c5de1 2458 if (cupsLastError() > IPP_OK_CONFLICT)
2459 cgiShowIPPError(_("Unable to get printer attributes:"));
2460 else
2461 cgiCopyTemplateLang("users.tmpl");
2462
2463 cgiEndHTML();
2464 }
2465 else
757d2cad 2466 {
2467 /*
323c5de1 2468 * Save the changes...
757d2cad 2469 */
2470
323c5de1 2471 for (num_users = 0, ptr = (char *)users; *ptr; num_users ++)
757d2cad 2472 {
323c5de1 2473 /*
2474 * Skip whitespace and commas...
2475 */
fa73b229 2476
323c5de1 2477 while (*ptr == ',' || isspace(*ptr & 255))
2478 ptr ++;
ef416fc2 2479
323c5de1 2480 if (*ptr == '\'' || *ptr == '\"')
2481 {
2482 /*
2483 * Scan quoted name...
2484 */
ef416fc2 2485
323c5de1 2486 quote = *ptr++;
ef416fc2 2487
323c5de1 2488 for (end = ptr; *end; end ++)
2489 if (*end == quote)
2490 break;
2491 }
2492 else
2493 {
2494 /*
2495 * Scan space or comma-delimited name...
2496 */
ef416fc2 2497
323c5de1 2498 for (end = ptr; *end; end ++)
2499 if (isspace(*end & 255) || *end == ',')
2500 break;
2501 }
ef416fc2 2502
323c5de1 2503 /*
2504 * Advance to the next name...
2505 */
ef416fc2 2506
323c5de1 2507 ptr = end;
2508 }
ef416fc2 2509
323c5de1 2510 /*
2511 * Build a CUPS-Add-Printer/Class request, which requires the following
2512 * attributes:
2513 *
2514 * attributes-charset
2515 * attributes-natural-language
2516 * printer-uri
2517 * requesting-user-name-{allowed,denied}
2518 */
ef416fc2 2519
323c5de1 2520 request = ippNewRequest(is_class ? CUPS_ADD_CLASS : CUPS_ADD_PRINTER);
ef416fc2 2521
323c5de1 2522 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
2523 "localhost", 0, is_class ? "/classes/%s" : "/printers/%s",
2524 printer);
2525 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
2526 NULL, uri);
f7deaa1a 2527
323c5de1 2528 if (num_users == 0)
2529 ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_NAME,
2530 "requesting-user-name-allowed", NULL, "all");
2531 else
2532 {
2533 attr = ippAddStrings(request, IPP_TAG_PRINTER, IPP_TAG_NAME,
2534 type, num_users, NULL, NULL);
ef416fc2 2535
323c5de1 2536 for (i = 0, ptr = (char *)users; *ptr; i ++)
2537 {
2538 /*
2539 * Skip whitespace and commas...
2540 */
ef416fc2 2541
323c5de1 2542 while (*ptr == ',' || isspace(*ptr & 255))
2543 ptr ++;
ef416fc2 2544
323c5de1 2545 if (*ptr == '\'' || *ptr == '\"')
2546 {
2547 /*
2548 * Scan quoted name...
2549 */
7594b224 2550
323c5de1 2551 quote = *ptr++;
7594b224 2552
323c5de1 2553 for (end = ptr; *end; end ++)
2554 if (*end == quote)
2555 break;
2556 }
2557 else
2558 {
2559 /*
2560 * Scan space or comma-delimited name...
2561 */
480ef0fe 2562
323c5de1 2563 for (end = ptr; *end; end ++)
2564 if (isspace(*end & 255) || *end == ',')
2565 break;
2566 }
ef416fc2 2567
323c5de1 2568 /*
2569 * Terminate the name...
2570 */
ef416fc2 2571
323c5de1 2572 if (*end)
2573 *end++ = '\0';
ef416fc2 2574
323c5de1 2575 /*
2576 * Add the name...
2577 */
ef416fc2 2578
323c5de1 2579 attr->values[i].string.text = strdup(ptr);
ef416fc2 2580
323c5de1 2581 /*
2582 * Advance to the next name...
2583 */
ef416fc2 2584
323c5de1 2585 ptr = end;
2586 }
2587 }
ef416fc2 2588
2589 /*
323c5de1 2590 * Do the request and get back a response...
ef416fc2 2591 */
2592
323c5de1 2593 ippDelete(cupsDoRequest(http, request, "/admin/"));
ef416fc2 2594
323c5de1 2595 if (cupsLastError() > IPP_OK_CONFLICT)
ef416fc2 2596 {
323c5de1 2597 cgiStartHTML(cgiText(_("Set Allowed Users")));
2598 cgiShowIPPError(_("Unable to change printer:"));
ef416fc2 2599 }
323c5de1 2600 else
ef416fc2 2601 {
2602 /*
323c5de1 2603 * Redirect successful updates back to the printer page...
ef416fc2 2604 */
2605
323c5de1 2606 char url[1024], /* Printer/class URL */
2607 refresh[1024]; /* Refresh URL */
ef416fc2 2608
2609
323c5de1 2610 cgiRewriteURL(uri, url, sizeof(url), NULL);
2611 cgiFormEncode(uri, url, sizeof(uri));
2612 snprintf(refresh, sizeof(refresh), "5;URL=/admin/?OP=redirect&URL=%s",
2613 uri);
2614 cgiSetVariable("refresh_page", refresh);
ef416fc2 2615
323c5de1 2616 cgiStartHTML(cgiText(_("Set Allowed Users")));
ef416fc2 2617
323c5de1 2618 cgiCopyTemplateLang(is_class ? "class-modified.tmpl" :
2619 "printer-modified.tmpl");
2620 }
ef416fc2 2621
323c5de1 2622 cgiEndHTML();
2623 }
2624}
ef416fc2 2625
ef416fc2 2626
323c5de1 2627/*
2628 * 'do_set_options()' - Configure the default options for a queue.
2629 */
ef416fc2 2630
323c5de1 2631static void
2632do_set_options(http_t *http, /* I - HTTP connection */
2633 int is_class) /* I - Set options for class? */
2634{
2635 int i, j, k, m; /* Looping vars */
2636 int have_options; /* Have options? */
2637 ipp_t *request, /* IPP request */
2638 *response; /* IPP response */
2639 ipp_attribute_t *attr; /* IPP attribute */
2640 char uri[HTTP_MAX_URI]; /* Job URI */
2641 const char *var; /* Variable value */
2642 const char *printer; /* Printer printer name */
2643 const char *filename; /* PPD filename */
2644 char tempfile[1024]; /* Temporary filename */
2645 cups_file_t *in, /* Input file */
2646 *out; /* Output file */
2647 char line[1024]; /* Line from PPD file */
2648 char keyword[1024], /* Keyword from Default line */
2649 *keyptr; /* Pointer into keyword... */
2650 ppd_file_t *ppd; /* PPD file */
2651 ppd_group_t *group; /* Option group */
2652 ppd_option_t *option; /* Option */
2653 ppd_attr_t *protocol; /* cupsProtocol attribute */
2654 const char *title; /* Page title */
ef416fc2 2655
ef416fc2 2656
323c5de1 2657 title = cgiText(is_class ? _("Set Class Options") : _("Set Printer Options"));
ef416fc2 2658
323c5de1 2659 fprintf(stderr, "DEBUG: do_set_options(http=%p, is_class=%d)\n", http,
2660 is_class);
ef416fc2 2661
323c5de1 2662 /*
2663 * Get the printer name...
2664 */
ef416fc2 2665
323c5de1 2666 if ((printer = cgiGetVariable("PRINTER_NAME")) != NULL)
2667 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
2668 "localhost", 0, is_class ? "/classes/%s" : "/printers/%s",
2669 printer);
2670 else
2671 {
2672 cgiSetVariable("ERROR", cgiText(_("Missing form variable!")));
2673 cgiStartHTML(title);
2674 cgiCopyTemplateLang("error.tmpl");
2675 cgiEndHTML();
2676 return;
2677 }
ef416fc2 2678
323c5de1 2679 fprintf(stderr, "DEBUG: printer=\"%s\", uri=\"%s\"...\n", printer, uri);
ef416fc2 2680
323c5de1 2681 /*
2682 * Get the PPD file...
2683 */
ef416fc2 2684
323c5de1 2685 if (is_class)
2686 filename = NULL;
2687 else
2688 filename = cupsGetPPD2(http, printer);
ef416fc2 2689
323c5de1 2690 if (filename)
2691 {
2692 fprintf(stderr, "DEBUG: Got PPD file: \"%s\"\n", filename);
ef416fc2 2693
323c5de1 2694 if ((ppd = ppdOpenFile(filename)) == NULL)
2695 {
2696 cgiSetVariable("ERROR", ppdErrorString(ppdLastError(&i)));
2697 cgiSetVariable("MESSAGE", cgiText(_("Unable to open PPD file:")));
2698 cgiStartHTML(title);
2699 cgiCopyTemplateLang("error.tmpl");
2700 cgiEndHTML();
2701 return;
2702 }
2703 }
2704 else
2705 {
2706 fputs("DEBUG: No PPD file\n", stderr);
2707 ppd = NULL;
2708 }
ef416fc2 2709
323c5de1 2710 if (cgiGetVariable("job_sheets_start") != NULL ||
2711 cgiGetVariable("job_sheets_end") != NULL)
2712 have_options = 1;
2713 else
2714 have_options = 0;
ef416fc2 2715
323c5de1 2716 if (ppd)
2717 {
2718 ppdMarkDefaults(ppd);
ef416fc2 2719
323c5de1 2720 DEBUG_printf(("<P>ppd->num_groups = %d\n"
2721 "<UL>\n", ppd->num_groups));
ef416fc2 2722
323c5de1 2723 for (i = ppd->num_groups, group = ppd->groups; i > 0; i --, group ++)
2724 {
2725 DEBUG_printf(("<LI>%s<UL>\n", group->text));
ef416fc2 2726
323c5de1 2727 for (j = group->num_options, option = group->options;
2728 j > 0;
2729 j --, option ++)
2730 if ((var = cgiGetVariable(option->keyword)) != NULL)
2731 {
2732 DEBUG_printf(("<LI>%s = \"%s\"</LI>\n", option->keyword, var));
2733 have_options = 1;
2734 ppdMarkOption(ppd, option->keyword, var);
ef416fc2 2735 }
323c5de1 2736#ifdef DEBUG
2737 else
2738 printf("<LI>%s not defined!</LI>\n", option->keyword);
2739#endif /* DEBUG */
ef416fc2 2740
323c5de1 2741 DEBUG_puts("</UL></LI>");
ef416fc2 2742 }
fa73b229 2743
323c5de1 2744 DEBUG_printf(("</UL>\n"
2745 "<P>ppdConflicts(ppd) = %d\n", ppdConflicts(ppd)));
2746 }
fa73b229 2747
323c5de1 2748 if (!have_options || ppdConflicts(ppd))
fa73b229 2749 {
2750 /*
323c5de1 2751 * Show the options to the user...
fa73b229 2752 */
2753
323c5de1 2754 fputs("DEBUG: Showing options...\n", stderr);
fa73b229 2755
323c5de1 2756 cgiStartHTML(cgiText(_("Set Printer Options")));
2757 cgiCopyTemplateLang("set-printer-options-header.tmpl");
fa73b229 2758
323c5de1 2759 if (ppd)
2760 {
2761 ppdLocalize(ppd);
f7deaa1a 2762
323c5de1 2763 if (ppdConflicts(ppd))
2764 {
2765 for (i = ppd->num_groups, k = 0, group = ppd->groups;
2766 i > 0;
2767 i --, group ++)
2768 for (j = group->num_options, option = group->options;
2769 j > 0;
2770 j --, option ++)
2771 if (option->conflicted)
2772 {
2773 cgiSetArray("ckeyword", k, option->keyword);
2774 cgiSetArray("ckeytext", k, option->text);
2775 k ++;
2776 }
f7deaa1a 2777
323c5de1 2778 cgiCopyTemplateLang("option-conflict.tmpl");
2779 }
f7deaa1a 2780
323c5de1 2781 for (i = ppd->num_groups, group = ppd->groups;
2782 i > 0;
2783 i --, group ++)
2784 {
2785 if (!strcmp(group->name, "InstallableOptions"))
2786 cgiSetVariable("GROUP", cgiText(_("Options Installed")));
2787 else
2788 cgiSetVariable("GROUP", group->text);
f7deaa1a 2789
323c5de1 2790 cgiCopyTemplateLang("option-header.tmpl");
2791
2792 for (j = group->num_options, option = group->options;
2793 j > 0;
2794 j --, option ++)
2795 {
2796 if (!strcmp(option->keyword, "PageRegion"))
2797 continue;
ef416fc2 2798
323c5de1 2799 cgiSetVariable("KEYWORD", option->keyword);
2800 cgiSetVariable("KEYTEXT", option->text);
2801
2802 if (option->conflicted)
2803 cgiSetVariable("CONFLICTED", "1");
2804 else
2805 cgiSetVariable("CONFLICTED", "0");
2806
2807 cgiSetSize("CHOICES", 0);
2808 cgiSetSize("TEXT", 0);
2809 for (k = 0, m = 0; k < option->num_choices; k ++)
2810 {
2811 /*
2812 * Hide custom option values...
2813 */
757d2cad 2814
323c5de1 2815 if (!strcmp(option->choices[k].choice, "Custom"))
2816 continue;
ef416fc2 2817
323c5de1 2818 cgiSetArray("CHOICES", m, option->choices[k].choice);
2819 cgiSetArray("TEXT", m, option->choices[k].text);
ef416fc2 2820
323c5de1 2821 m ++;
ef416fc2 2822
323c5de1 2823 if (option->choices[k].marked)
2824 cgiSetVariable("DEFCHOICE", option->choices[k].choice);
2825 }
ef416fc2 2826
323c5de1 2827 switch (option->ui)
2828 {
2829 case PPD_UI_BOOLEAN :
2830 cgiCopyTemplateLang("option-boolean.tmpl");
2831 break;
2832 case PPD_UI_PICKONE :
2833 cgiCopyTemplateLang("option-pickone.tmpl");
2834 break;
2835 case PPD_UI_PICKMANY :
2836 cgiCopyTemplateLang("option-pickmany.tmpl");
2837 break;
2838 }
2839 }
ef416fc2 2840
323c5de1 2841 cgiCopyTemplateLang("option-trailer.tmpl");
2842 }
2843 }
ef416fc2 2844
323c5de1 2845 /*
2846 * Build an IPP_GET_PRINTER_ATTRIBUTES request, which requires the
2847 * following attributes:
2848 *
2849 * attributes-charset
2850 * attributes-natural-language
2851 * printer-uri
2852 */
fa73b229 2853
323c5de1 2854 request = ippNewRequest(IPP_GET_PRINTER_ATTRIBUTES);
ef416fc2 2855
323c5de1 2856 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
2857 "localhost", 0, "/printers/%s", printer);
2858 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
2859 NULL, uri);
ef416fc2 2860
323c5de1 2861 /*
2862 * Do the request and get back a response...
2863 */
ef416fc2 2864
323c5de1 2865 if ((response = cupsDoRequest(http, request, "/")) != NULL)
2866 {
2867 if ((attr = ippFindAttribute(response, "job-sheets-supported",
2868 IPP_TAG_ZERO)) != NULL)
2869 {
2870 /*
2871 * Add the job sheets options...
2872 */
ef416fc2 2873
323c5de1 2874 cgiSetVariable("GROUP", cgiText(_("Banners")));
2875 cgiCopyTemplateLang("option-header.tmpl");
ef416fc2 2876
323c5de1 2877 cgiSetSize("CHOICES", attr->num_values);
2878 cgiSetSize("TEXT", attr->num_values);
2879 for (k = 0; k < attr->num_values; k ++)
2880 {
2881 cgiSetArray("CHOICES", k, attr->values[k].string.text);
2882 cgiSetArray("TEXT", k, attr->values[k].string.text);
2883 }
ef416fc2 2884
323c5de1 2885 attr = ippFindAttribute(response, "job-sheets-default", IPP_TAG_ZERO);
ef416fc2 2886
323c5de1 2887 cgiSetVariable("KEYWORD", "job_sheets_start");
2888 cgiSetVariable("KEYTEXT", cgiText(_("Starting Banner")));
2889 cgiSetVariable("DEFCHOICE", attr == NULL ?
2890 "" : attr->values[0].string.text);
ef416fc2 2891
323c5de1 2892 cgiCopyTemplateLang("option-pickone.tmpl");
fa73b229 2893
323c5de1 2894 cgiSetVariable("KEYWORD", "job_sheets_end");
2895 cgiSetVariable("KEYTEXT", cgiText(_("Ending Banner")));
2896 cgiSetVariable("DEFCHOICE", attr == NULL && attr->num_values > 1 ?
2897 "" : attr->values[1].string.text);
ef416fc2 2898
323c5de1 2899 cgiCopyTemplateLang("option-pickone.tmpl");
ef416fc2 2900
323c5de1 2901 cgiCopyTemplateLang("option-trailer.tmpl");
2902 }
ef416fc2 2903
323c5de1 2904 if (ippFindAttribute(response, "printer-error-policy-supported",
2905 IPP_TAG_ZERO) ||
2906 ippFindAttribute(response, "printer-op-policy-supported",
2907 IPP_TAG_ZERO))
2908 {
2909 /*
2910 * Add the error and operation policy options...
2911 */
ef416fc2 2912
323c5de1 2913 cgiSetVariable("GROUP", cgiText(_("Policies")));
2914 cgiCopyTemplateLang("option-header.tmpl");
ef416fc2 2915
323c5de1 2916 /*
2917 * Error policy...
2918 */
ef416fc2 2919
323c5de1 2920 attr = ippFindAttribute(response, "printer-error-policy-supported",
2921 IPP_TAG_ZERO);
2922
2923 if (attr)
2924 {
2925 cgiSetSize("CHOICES", attr->num_values);
2926 cgiSetSize("TEXT", attr->num_values);
2927 for (k = 0; k < attr->num_values; k ++)
2928 {
2929 cgiSetArray("CHOICES", k, attr->values[k].string.text);
2930 cgiSetArray("TEXT", k, attr->values[k].string.text);
2931 }
ef416fc2 2932
323c5de1 2933 attr = ippFindAttribute(response, "printer-error-policy",
2934 IPP_TAG_ZERO);
ef416fc2 2935
323c5de1 2936 cgiSetVariable("KEYWORD", "printer_error_policy");
2937 cgiSetVariable("KEYTEXT", cgiText(_("Error Policy")));
2938 cgiSetVariable("DEFCHOICE", attr == NULL ?
2939 "" : attr->values[0].string.text);
2940 }
fa73b229 2941
323c5de1 2942 cgiCopyTemplateLang("option-pickone.tmpl");
ef416fc2 2943
323c5de1 2944 /*
2945 * Operation policy...
2946 */
ef416fc2 2947
323c5de1 2948 attr = ippFindAttribute(response, "printer-op-policy-supported",
2949 IPP_TAG_ZERO);
ef416fc2 2950
323c5de1 2951 if (attr)
2952 {
2953 cgiSetSize("CHOICES", attr->num_values);
2954 cgiSetSize("TEXT", attr->num_values);
2955 for (k = 0; k < attr->num_values; k ++)
2956 {
2957 cgiSetArray("CHOICES", k, attr->values[k].string.text);
2958 cgiSetArray("TEXT", k, attr->values[k].string.text);
2959 }
ef416fc2 2960
323c5de1 2961 attr = ippFindAttribute(response, "printer-op-policy", IPP_TAG_ZERO);
ef416fc2 2962
323c5de1 2963 cgiSetVariable("KEYWORD", "printer_op_policy");
2964 cgiSetVariable("KEYTEXT", cgiText(_("Operation Policy")));
2965 cgiSetVariable("DEFCHOICE", attr == NULL ?
2966 "" : attr->values[0].string.text);
ef416fc2 2967
323c5de1 2968 cgiCopyTemplateLang("option-pickone.tmpl");
2969 }
ef416fc2 2970
323c5de1 2971 cgiCopyTemplateLang("option-trailer.tmpl");
2972 }
ef416fc2 2973
2974 ippDelete(response);
2975 }
ef416fc2 2976
ef416fc2 2977 /*
323c5de1 2978 * Binary protocol support...
ef416fc2 2979 */
2980
323c5de1 2981 if (ppd->protocols && strstr(ppd->protocols, "BCP"))
ef416fc2 2982 {
323c5de1 2983 protocol = ppdFindAttr(ppd, "cupsProtocol", NULL);
ef416fc2 2984
323c5de1 2985 cgiSetVariable("GROUP", cgiText(_("PS Binary Protocol")));
2986 cgiCopyTemplateLang("option-header.tmpl");
ef416fc2 2987
323c5de1 2988 cgiSetSize("CHOICES", 2);
2989 cgiSetSize("TEXT", 2);
2990 cgiSetArray("CHOICES", 0, "None");
2991 cgiSetArray("TEXT", 0, cgiText(_("None")));
ef416fc2 2992
323c5de1 2993 if (strstr(ppd->protocols, "TBCP"))
2994 {
2995 cgiSetArray("CHOICES", 1, "TBCP");
2996 cgiSetArray("TEXT", 1, "TBCP");
ef416fc2 2997 }
2998 else
2999 {
323c5de1 3000 cgiSetArray("CHOICES", 1, "BCP");
3001 cgiSetArray("TEXT", 1, "BCP");
ef416fc2 3002 }
3003
323c5de1 3004 cgiSetVariable("KEYWORD", "protocol");
3005 cgiSetVariable("KEYTEXT", cgiText(_("PS Binary Protocol")));
3006 cgiSetVariable("DEFCHOICE", protocol ? protocol->value : "None");
ef416fc2 3007
323c5de1 3008 cgiCopyTemplateLang("option-pickone.tmpl");
3009
3010 cgiCopyTemplateLang("option-trailer.tmpl");
ef416fc2 3011 }
3012
323c5de1 3013 cgiCopyTemplateLang("set-printer-options-trailer.tmpl");
3014 cgiEndHTML();
3015 }
3016 else
3017 {
ef416fc2 3018 /*
323c5de1 3019 * Set default options...
ef416fc2 3020 */
3021
323c5de1 3022 fputs("DEBUG: Setting options...\n", stderr);
ef416fc2 3023
323c5de1 3024 if (filename)
ef416fc2 3025 {
323c5de1 3026 out = cupsTempFile2(tempfile, sizeof(tempfile));
3027 in = cupsFileOpen(filename, "r");
ef416fc2 3028
323c5de1 3029 if (!in || !out)
ef416fc2 3030 {
323c5de1 3031 cgiSetVariable("ERROR", strerror(errno));
3032 cgiStartHTML(cgiText(_("Set Printer Options")));
3033 cgiCopyTemplateLang("error.tmpl");
3034 cgiEndHTML();
ef416fc2 3035
323c5de1 3036 if (in)
3037 cupsFileClose(in);
ef416fc2 3038
323c5de1 3039 if (out)
ef416fc2 3040 {
323c5de1 3041 cupsFileClose(out);
3042 unlink(tempfile);
3043 }
ef416fc2 3044
323c5de1 3045 unlink(filename);
3046 return;
3047 }
ef416fc2 3048
323c5de1 3049 while (cupsFileGets(in, line, sizeof(line)))
3050 {
3051 if (!strncmp(line, "*cupsProtocol:", 14) && cgiGetVariable("protocol"))
3052 continue;
3053 else if (strncmp(line, "*Default", 8))
3054 cupsFilePrintf(out, "%s\n", line);
ef416fc2 3055 else
3056 {
3057 /*
323c5de1 3058 * Get default option name...
ef416fc2 3059 */
3060
323c5de1 3061 strlcpy(keyword, line + 8, sizeof(keyword));
3062
3063 for (keyptr = keyword; *keyptr; keyptr ++)
3064 if (*keyptr == ':' || isspace(*keyptr & 255))
ef416fc2 3065 break;
ef416fc2 3066
323c5de1 3067 *keyptr = '\0';
ef416fc2 3068
323c5de1 3069 if (!strcmp(keyword, "PageRegion") ||
3070 !strcmp(keyword, "PaperDimension") ||
3071 !strcmp(keyword, "ImageableArea"))
3072 var = cgiGetVariable("PageSize");
3073 else
3074 var = cgiGetVariable(keyword);
ef416fc2 3075
323c5de1 3076 if (var != NULL)
3077 cupsFilePrintf(out, "*Default%s: %s\n", keyword, var);
3078 else
3079 cupsFilePrintf(out, "%s\n", line);
3080 }
3081 }
ef416fc2 3082
323c5de1 3083 if ((var = cgiGetVariable("protocol")) != NULL)
3084 cupsFilePrintf(out, "*cupsProtocol: %s\n", cgiGetVariable("protocol"));
ef416fc2 3085
323c5de1 3086 cupsFileClose(in);
3087 cupsFileClose(out);
3088 }
3089 else
3090 {
3091 /*
3092 * Make sure temporary filename is cleared when there is no PPD...
3093 */
ef416fc2 3094
323c5de1 3095 tempfile[0] = '\0';
ef416fc2 3096 }
3097
323c5de1 3098 /*
3099 * Build a CUPS_ADD_MODIFY_CLASS/PRINTER request, which requires the
3100 * following attributes:
3101 *
3102 * attributes-charset
3103 * attributes-natural-language
3104 * printer-uri
3105 * job-sheets-default
3106 * printer-error-policy
3107 * printer-op-policy
3108 * [ppd file]
3109 */
3110
3111 request = ippNewRequest(is_class ? CUPS_ADD_MODIFY_CLASS :
3112 CUPS_ADD_MODIFY_PRINTER);
3113
3114 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
3115 NULL, uri);
3116
3117 attr = ippAddStrings(request, IPP_TAG_PRINTER, IPP_TAG_NAME,
3118 "job-sheets-default", 2, NULL, NULL);
3119 attr->values[0].string.text = _cupsStrAlloc(cgiGetVariable("job_sheets_start"));
3120 attr->values[1].string.text = _cupsStrAlloc(cgiGetVariable("job_sheets_end"));
3121
3122 if ((var = cgiGetVariable("printer_error_policy")) != NULL)
3123 attr = ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_NAME,
3124 "printer-error-policy", NULL, var);
3125
3126 if ((var = cgiGetVariable("printer_op_policy")) != NULL)
3127 attr = ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_NAME,
3128 "printer-op-policy", NULL, var);
3129
ef416fc2 3130 /*
3131 * Do the request and get back a response...
3132 */
3133
323c5de1 3134 if (filename)
3135 ippDelete(cupsDoFileRequest(http, request, "/admin/", tempfile));
3136 else
3137 ippDelete(cupsDoRequest(http, request, "/admin/"));
ef416fc2 3138
fa73b229 3139 if (cupsLastError() > IPP_OK_CONFLICT)
ef416fc2 3140 {
323c5de1 3141 cgiStartHTML(title);
3142 cgiShowIPPError(_("Unable to set options:"));
ef416fc2 3143 }
3144 else
3145 {
3146 /*
3147 * Redirect successful updates back to the printer page...
3148 */
3149
323c5de1 3150 char refresh[1024]; /* Refresh URL */
ef416fc2 3151
fa73b229 3152
323c5de1 3153 cgiFormEncode(uri, printer, sizeof(uri));
3154 snprintf(refresh, sizeof(refresh), "5;URL=/admin/?OP=redirect&URL=/%s/%s",
3155 is_class ? "classes" : "printers", uri);
ef416fc2 3156 cgiSetVariable("refresh_page", refresh);
3157
323c5de1 3158 cgiStartHTML(title);
ef416fc2 3159
323c5de1 3160 cgiCopyTemplateLang("printer-configured.tmpl");
ef416fc2 3161 }
3162
3163 cgiEndHTML();
323c5de1 3164
3165 if (filename)
3166 unlink(tempfile);
ef416fc2 3167 }
323c5de1 3168
3169 if (filename)
3170 unlink(filename);
ef416fc2 3171}
3172
3173
3174/*
3175 * 'do_set_sharing()' - Set printer-is-shared value...
3176 */
3177
3178static void
fa73b229 3179do_set_sharing(http_t *http) /* I - HTTP connection */
ef416fc2 3180{
3181 ipp_t *request, /* IPP request */
3182 *response; /* IPP response */
3183 char uri[HTTP_MAX_URI]; /* Printer URI */
3184 const char *printer, /* Printer name */
fa73b229 3185 *is_class, /* Is a class? */
ef416fc2 3186 *shared; /* Sharing value */
ef416fc2 3187
3188
fa73b229 3189 is_class = cgiGetVariable("IS_CLASS");
3190 printer = cgiGetVariable("PRINTER_NAME");
3191 shared = cgiGetVariable("SHARED");
ef416fc2 3192
fa73b229 3193 if (!printer || !shared)
ef416fc2 3194 {
fa73b229 3195 cgiSetVariable("ERROR", cgiText(_("Missing form variable!")));
3196 cgiStartHTML(cgiText(_("Set Publishing")));
ef416fc2 3197 cgiCopyTemplateLang("error.tmpl");
3198 cgiEndHTML();
3199 return;
3200 }
3201
3202 /*
fa73b229 3203 * Build a CUPS-Add-Printer/CUPS-Add-Class request, which requires the
3204 * following attributes:
ef416fc2 3205 *
3206 * attributes-charset
3207 * attributes-natural-language
3208 * printer-uri
3209 * printer-is-shared
3210 */
3211
fa73b229 3212 request = ippNewRequest(is_class ? CUPS_ADD_CLASS : CUPS_ADD_PRINTER);
ef416fc2 3213
a4d04587 3214 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
3215 "localhost", 0, is_class ? "/classes/%s" : "/printers/%s",
3216 printer);
ef416fc2 3217 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
3218 NULL, uri);
3219
3220 ippAddBoolean(request, IPP_TAG_OPERATION, "printer-is-shared", atoi(shared));
3221
3222 /*
3223 * Do the request and get back a response...
3224 */
3225
3226 if ((response = cupsDoRequest(http, request, "/admin/")) != NULL)
3227 {
ef416fc2 3228 cgiSetIPPVars(response, NULL, NULL, NULL, 0);
3229
3230 ippDelete(response);
3231 }
ef416fc2 3232
fa73b229 3233 if (cupsLastError() > IPP_OK_CONFLICT)
ef416fc2 3234 {
fa73b229 3235 cgiStartHTML(cgiText(_("Set Publishing")));
3236 cgiShowIPPError(_("Unable to change printer-is-shared attribute:"));
ef416fc2 3237 }
3238 else
3239 {
3240 /*
3241 * Redirect successful updates back to the printer page...
3242 */
3243
fa73b229 3244 char url[1024], /* Printer/class URL */
3245 refresh[1024]; /* Refresh URL */
ef416fc2 3246
ef416fc2 3247
fa73b229 3248 cgiRewriteURL(uri, url, sizeof(url), NULL);
3249 cgiFormEncode(uri, url, sizeof(uri));
f301802f 3250 snprintf(refresh, sizeof(refresh), "5;URL=/admin/?OP=redirect&URL=%s", uri);
fa73b229 3251 cgiSetVariable("refresh_page", refresh);
ef416fc2 3252
fa73b229 3253 cgiStartHTML(cgiText(_("Set Publishing")));
3254 cgiCopyTemplateLang(is_class ? "class-modified.tmpl" :
3255 "printer-modified.tmpl");
ef416fc2 3256 }
3257
3258 cgiEndHTML();
3259}
3260
3261
3262/*
3263 * 'match_string()' - Return the number of matching characters.
3264 */
3265
3266static int /* O - Number of matching characters */
3267match_string(const char *a, /* I - First string */
3268 const char *b) /* I - Second string */
3269{
3270 int count; /* Number of matching characters */
3271
3272
3273 /*
3274 * Loop through both strings until we hit the end of either or we find
3275 * a non-matching character. For the purposes of comparison, we ignore
3276 * whitespace and do a case-insensitive comparison so that we have a
3277 * better chance of finding a match...
3278 */
3279
3280 for (count = 0; *a && *b; a++, b++, count ++)
3281 {
3282 /*
3283 * Skip leading whitespace characters...
3284 */
3285
3286 while (isspace(*a & 255))
3287 a ++;
3288
3289 while (isspace(*b & 255))
3290 b ++;
3291
3292 /*
3293 * Break out if we run out of characters...
3294 */
3295
3296 if (!*a || !*b)
3297 break;
3298
3299 /*
3300 * Do a case-insensitive comparison of the next two chars...
3301 */
3302
3303 if (tolower(*a & 255) != tolower(*b & 255))
3304 break;
3305 }
3306
3307 return (count);
3308}
3309
3310
3311/*
323c5de1 3312 * End of "$Id: admin.c 6440 2007-04-03 23:17:17Z mike $".
ef416fc2 3313 */