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