]> git.ipfire.org Git - thirdparty/cups.git/blame - cgi-bin/admin.c
Remove svn:keywords since they cause svn_load_dirs.pl to complain about every file.
[thirdparty/cups.git] / cgi-bin / admin.c
CommitLineData
ef416fc2 1/*
c07d5b2d 2 * "$Id: admin.c 181 2006-06-22 20:01:18Z jlovell $"
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
654 if ((response = cupsDoRequest(http, request, "/")) != NULL)
655 {
a4d04587 656 fputs("DEBUG: Got device list!\n", stderr);
657
ef416fc2 658 cgiSetIPPVars(response, NULL, NULL, NULL, 0);
659 ippDelete(response);
660 }
a4d04587 661 else
662 fprintf(stderr,
663 "ERROR: CUPS-Get-Devices request failed with status %x: %s\n",
664 cupsLastError(), cupsLastErrorString());
ef416fc2 665
666 /*
667 * Let the user choose...
668 */
669
670 if ((attr = ippFindAttribute(oldinfo, "device-uri", IPP_TAG_URI)) != NULL)
671 {
672 strlcpy(uri, attr->values[0].string.text, sizeof(uri));
673 if ((uriptr = strchr(uri, ':')) != NULL && strncmp(uriptr, "://", 3) == 0)
674 *uriptr = '\0';
675
676 cgiSetVariable("CURRENT_DEVICE_URI", attr->values[0].string.text);
677 cgiSetVariable("CURRENT_DEVICE_SCHEME", uri);
678 }
679
680 cgiStartHTML(title);
681 cgiCopyTemplateLang("choose-device.tmpl");
682 cgiEndHTML();
683 }
684 else if (strchr(var, '/') == NULL)
685 {
686 if ((attr = ippFindAttribute(oldinfo, "device-uri", IPP_TAG_URI)) != NULL)
687 {
688 /*
689 * Set the current device URI for the form to the old one...
690 */
691
692 if (strncmp(attr->values[0].string.text, var, strlen(var)) == 0)
693 cgiSetVariable("DEVICE_URI", attr->values[0].string.text);
694 }
695
696 /*
697 * User needs to set the full URI...
698 */
699
700 cgiStartHTML(title);
701 cgiCopyTemplateLang("choose-uri.tmpl");
702 cgiEndHTML();
703 }
704 else if (!strncmp(var, "serial:", 7) && !cgiGetVariable("BAUDRATE"))
705 {
706 /*
707 * Need baud rate, parity, etc.
708 */
709
710 if ((var = strchr(var, '?')) != NULL &&
711 strncmp(var, "?baud=", 6) == 0)
712 maxrate = atoi(var + 6);
713 else
714 maxrate = 19200;
715
716 for (i = 0; i < 10; i ++)
717 if (baudrates[i] > maxrate)
718 break;
719 else
720 {
721 sprintf(baudrate, "%d", baudrates[i]);
722 cgiSetArray("BAUDRATES", i, baudrate);
723 }
724
725 cgiStartHTML(title);
726 cgiCopyTemplateLang("choose-serial.tmpl");
727 cgiEndHTML();
728 }
729 else if (!file && (var = cgiGetVariable("PPD_NAME")) == NULL)
730 {
731 if (modify)
732 {
733 /*
734 * Get the PPD file...
735 */
736
737 int fd; /* PPD file */
738 char filename[1024]; /* PPD filename */
739 ppd_file_t *ppd; /* PPD information */
740 char buffer[1024]; /* Buffer */
741 int bytes; /* Number of bytes */
742 http_status_t get_status; /* Status of GET */
743
744
a4d04587 745 /* TODO: Use cupsGetFile() API... */
ef416fc2 746 snprintf(uri, sizeof(uri), "/printers/%s.ppd", name);
747
748 if (httpGet(http, uri))
749 httpGet(http, uri);
750
751 while ((get_status = httpUpdate(http)) == HTTP_CONTINUE);
752
753 if (get_status != HTTP_OK)
754 {
755 fprintf(stderr, "ERROR: Unable to get PPD file %s: %d - %s\n",
756 uri, get_status, httpStatus(get_status));
757 }
758 else if ((fd = cupsTempFd(filename, sizeof(filename))) >= 0)
759 {
a4d04587 760 while ((bytes = httpRead2(http, buffer, sizeof(buffer))) > 0)
ef416fc2 761 write(fd, buffer, bytes);
762
763 close(fd);
764
765 if ((ppd = ppdOpenFile(filename)) != NULL)
766 {
767 if (ppd->manufacturer)
768 cgiSetVariable("CURRENT_MAKE", ppd->manufacturer);
769
770 if (ppd->nickname)
771 cgiSetVariable("CURRENT_MAKE_AND_MODEL", ppd->nickname);
772
773 ppdClose(ppd);
774 unlink(filename);
775 }
776 else
777 {
778 fprintf(stderr, "ERROR: Unable to open PPD file %s: %s\n",
779 filename, ppdErrorString(ppdLastError(&bytes)));
780 }
781 }
782 else
783 {
784 httpFlush(http);
785
786 fprintf(stderr,
787 "ERROR: Unable to create temporary file for PPD file: %s\n",
788 strerror(errno));
789 }
790 }
791 else if ((uriptr = strrchr(cgiGetVariable("DEVICE_URI"), '|')) != NULL)
792 {
793 /*
794 * Extract make and make/model from device URI string...
795 */
796
797 char make[1024], /* Make string */
798 *makeptr; /* Pointer into make */
799
800
801 *uriptr++ = '\0';
802
803 strlcpy(make, uriptr, sizeof(make));
804
805 if ((makeptr = strchr(make, ' ')) != NULL)
806 *makeptr = '\0';
807 else if ((makeptr = strchr(make, '-')) != NULL)
808 *makeptr = '\0';
809 else if (!strncasecmp(make, "laserjet", 8) ||
810 !strncasecmp(make, "deskjet", 7) ||
811 !strncasecmp(make, "designjet", 9))
812 strcpy(make, "HP");
813 else if (!strncasecmp(make, "phaser", 6))
814 strcpy(make, "Xerox");
815 else if (!strncasecmp(make, "stylus", 6))
816 strcpy(make, "Epson");
817 else
818 strcpy(make, "Generic");
819
820 cgiSetVariable("CURRENT_MAKE", make);
821 cgiSetVariable("PPD_MAKE", make);
822 cgiSetVariable("CURRENT_MAKE_AND_MODEL", uriptr);
823 }
824
825 /*
826 * Build a CUPS_GET_PPDS request, which requires the following
827 * attributes:
828 *
829 * attributes-charset
830 * attributes-natural-language
831 * printer-uri
832 */
833
fa73b229 834 request = ippNewRequest(CUPS_GET_PPDS);
ef416fc2 835
836 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
837 NULL, "ipp://localhost/printers/");
838
ef416fc2 839 if ((var = cgiGetVariable("PPD_MAKE")) != NULL)
840 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_TEXT,
841 "ppd-make", NULL, var);
842 else
843 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
844 "requested-attributes", NULL, "ppd-make");
845
846 /*
847 * Do the request and get back a response...
848 */
849
850 if ((response = cupsDoRequest(http, request, "/")) != NULL)
851 {
852 /*
853 * Got the list of PPDs, see if the user has selected a make...
854 */
855
89d46774 856 if (cgiSetIPPVars(response, NULL, NULL, NULL, 0) == 0)
ef416fc2 857 {
858 /*
89d46774 859 * No PPD files with this make, try again with all makes...
ef416fc2 860 */
861
89d46774 862 ippDelete(response);
863
864 request = ippNewRequest(CUPS_GET_PPDS);
865
866 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
867 NULL, "ipp://localhost/printers/");
868
869 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
870 "requested-attributes", NULL, "ppd-make");
ef416fc2 871
89d46774 872 if ((response = cupsDoRequest(http, request, "/")) != NULL)
873 cgiSetIPPVars(response, NULL, NULL, NULL, 0);
874
875 cgiStartHTML(title);
876 cgiCopyTemplateLang("choose-make.tmpl");
877 cgiEndHTML();
878 }
879 else if (!var)
880 {
ef416fc2 881 cgiStartHTML(title);
882 cgiCopyTemplateLang("choose-make.tmpl");
883 cgiEndHTML();
884 }
885 else
886 {
887 /*
888 * Let the user choose a model...
889 */
890
891 const char *make_model; /* Current make/model string */
892
893
894 if ((make_model = cgiGetVariable("CURRENT_MAKE_AND_MODEL")) != NULL)
895 {
896 /*
897 * Scan for "close" matches...
898 */
899
900 int match, /* Current match */
901 best_match, /* Best match so far */
902 count; /* Number of drivers */
903 const char *best, /* Best matching string */
904 *current; /* Current string */
905
906
907 count = cgiGetSize("PPD_MAKE_AND_MODEL");
908
909 for (i = 0, best_match = 0, best = NULL; i < count; i ++)
910 {
911 current = cgiGetArray("PPD_MAKE_AND_MODEL", i);
912 match = match_string(make_model, current);
913
914 if (match > best_match)
915 {
916 best_match = match;
917 best = current;
918 }
919 }
920
921 if (best_match > strlen(var))
922 {
923 /*
924 * Found a match longer than the make...
925 */
926
927 cgiSetVariable("CURRENT_MAKE_AND_MODEL", best);
928 }
929 }
930
931 cgiStartHTML(title);
932 cgiCopyTemplateLang("choose-model.tmpl");
933 cgiEndHTML();
934 }
935
ef416fc2 936 ippDelete(response);
937 }
938 else
939 {
ef416fc2 940 cgiStartHTML(title);
fa73b229 941 cgiShowIPPError(_("Unable to get list of printer drivers:"));
ef416fc2 942 cgiCopyTemplateLang("error.tmpl");
943 cgiEndHTML();
944 }
945 }
946 else
947 {
948 /*
949 * Build a CUPS_ADD_PRINTER request, which requires the following
950 * attributes:
951 *
952 * attributes-charset
953 * attributes-natural-language
954 * printer-uri
955 * printer-location
956 * printer-info
957 * ppd-name
958 * device-uri
959 * printer-is-accepting-jobs
960 * printer-state
961 */
962
fa73b229 963 request = ippNewRequest(CUPS_ADD_PRINTER);
ef416fc2 964
a4d04587 965 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
966 "localhost", 0, "/printers/%s",
967 cgiGetVariable("PRINTER_NAME"));
ef416fc2 968 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
969 NULL, uri);
970
971 ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-location",
972 NULL, cgiGetVariable("PRINTER_LOCATION"));
973
974 ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-info",
975 NULL, cgiGetVariable("PRINTER_INFO"));
976
977 if (!file)
978 ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_NAME, "ppd-name",
979 NULL, cgiGetVariable("PPD_NAME"));
980
981 strlcpy(uri, cgiGetVariable("DEVICE_URI"), sizeof(uri));
982
983 /*
984 * Strip make and model from URI...
985 */
986
987 if ((uriptr = strrchr(uri, '|')) != NULL)
988 *uriptr = '\0';
989
fa73b229 990 if (!strncmp(uri, "serial:", 7))
ef416fc2 991 {
992 /*
993 * Update serial port URI to include baud rate, etc.
994 */
995
996 if ((uriptr = strchr(uri, '?')) == NULL)
997 uriptr = uri + strlen(uri);
998
999 snprintf(uriptr, sizeof(uri) - (uriptr - uri),
1000 "?baud=%s+bits=%s+parity=%s+flow=%s",
1001 cgiGetVariable("BAUDRATE"), cgiGetVariable("BITS"),
1002 cgiGetVariable("PARITY"), cgiGetVariable("FLOW"));
1003 }
1004
1005 ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_URI, "device-uri",
1006 NULL, uri);
1007
1008 ippAddBoolean(request, IPP_TAG_PRINTER, "printer-is-accepting-jobs", 1);
1009
1010 ippAddInteger(request, IPP_TAG_PRINTER, IPP_TAG_ENUM, "printer-state",
1011 IPP_PRINTER_IDLE);
1012
1013 /*
1014 * Do the request and get back a response...
1015 */
1016
1017 if (file)
fa73b229 1018 ippDelete(cupsDoFileRequest(http, request, "/admin/", file->tempfile));
ef416fc2 1019 else
fa73b229 1020 ippDelete(cupsDoRequest(http, request, "/admin/"));
ef416fc2 1021
fa73b229 1022 if (cupsLastError() > IPP_OK_CONFLICT)
ef416fc2 1023 {
1024 cgiStartHTML(title);
fa73b229 1025 cgiShowIPPError(modify ? _("Unable to modify printer:") :
1026 _("Unable to add printer:"));
ef416fc2 1027 }
1028 else
1029 {
1030 /*
1031 * Redirect successful updates back to the printer or set-options pages...
1032 */
1033
1034 char refresh[1024]; /* Refresh URL */
1035
1036
1037 cgiFormEncode(uri, name, sizeof(uri));
1038
1039 if (modify)
1040 snprintf(refresh, sizeof(refresh),
fa73b229 1041 "5;/admin/?OP=redirect&URL=/printers/%s", uri);
ef416fc2 1042 else
1043 snprintf(refresh, sizeof(refresh),
f301802f 1044 "5;URL=/admin/?OP=set-printer-options&PRINTER_NAME=%s", uri);
ef416fc2 1045
1046 cgiSetVariable("refresh_page", refresh);
1047
1048 cgiStartHTML(title);
1049
1050 if (modify)
1051 cgiCopyTemplateLang("printer-modified.tmpl");
1052 else
1053 cgiCopyTemplateLang("printer-added.tmpl");
1054 }
1055
1056 cgiEndHTML();
1057 }
1058
1059 if (oldinfo)
1060 ippDelete(oldinfo);
1061}
1062
1063
1064/*
1065 * 'do_config_printer()' - Configure the default options for a printer.
1066 */
1067
1068static void
fa73b229 1069do_config_printer(http_t *http) /* I - HTTP connection */
ef416fc2 1070{
1071 int i, j, k, m; /* Looping vars */
1072 int have_options; /* Have options? */
1073 ipp_t *request, /* IPP request */
1074 *response; /* IPP response */
1075 ipp_attribute_t *attr; /* IPP attribute */
1076 char uri[HTTP_MAX_URI]; /* Job URI */
1077 const char *var; /* Variable value */
1078 const char *printer; /* Printer printer name */
ef416fc2 1079 const char *filename; /* PPD filename */
1080 char tempfile[1024]; /* Temporary filename */
1081 cups_file_t *in, /* Input file */
1082 *out; /* Output file */
1083 char line[1024]; /* Line from PPD file */
1084 char keyword[1024], /* Keyword from Default line */
1085 *keyptr; /* Pointer into keyword... */
1086 ppd_file_t *ppd; /* PPD file */
1087 ppd_group_t *group; /* Option group */
1088 ppd_option_t *option; /* Option */
1089 ppd_attr_t *protocol; /* cupsProtocol attribute */
fa73b229 1090 const char *title; /* Page title */
ef416fc2 1091
1092
fa73b229 1093 title = cgiText(_("Set Printer Options"));
1094
bd7854cb 1095 fprintf(stderr, "DEBUG: do_config_printer(http=%p)\n", http);
1096
ef416fc2 1097 /*
1098 * Get the printer name...
1099 */
1100
1101 if ((printer = cgiGetVariable("PRINTER_NAME")) != NULL)
a4d04587 1102 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
1103 "localhost", 0, "/printers/%s", printer);
ef416fc2 1104 else
1105 {
fa73b229 1106 cgiSetVariable("ERROR", cgiText(_("Missing form variable!")));
1107 cgiStartHTML(title);
ef416fc2 1108 cgiCopyTemplateLang("error.tmpl");
1109 cgiEndHTML();
1110 return;
1111 }
1112
bd7854cb 1113 fprintf(stderr, "DEBUG: printer=\"%s\", uri=\"%s\"...\n", printer, uri);
1114
ef416fc2 1115 /*
1116 * Get the PPD file...
1117 */
1118
bd7854cb 1119 if ((filename = cupsGetPPD2(http, printer)) == NULL)
ef416fc2 1120 {
bd7854cb 1121 fputs("DEBUG: No PPD file!?!\n", stderr);
1122
fa73b229 1123 cgiStartHTML(title);
1124 cgiShowIPPError(_("Unable to get PPD file!"));
1125 cgiEndHTML();
ef416fc2 1126 return;
1127 }
1128
bd7854cb 1129 fprintf(stderr, "DEBUG: Got PPD file: \"%s\"\n", filename);
1130
ef416fc2 1131 if ((ppd = ppdOpenFile(filename)) == NULL)
1132 {
fa73b229 1133 cgiSetVariable("ERROR", ppdErrorString(ppdLastError(&i)));
1134 cgiSetVariable("MESSAGE", cgiText(_("Unable to open PPD file:")));
1135 cgiStartHTML(title);
ef416fc2 1136 cgiCopyTemplateLang("error.tmpl");
1137 cgiEndHTML();
1138 return;
1139 }
1140
1141 if (cgiGetVariable("job_sheets_start") != NULL ||
1142 cgiGetVariable("job_sheets_end") != NULL)
1143 have_options = 1;
1144 else
1145 have_options = 0;
1146
1147 ppdMarkDefaults(ppd);
1148
1149 DEBUG_printf(("<P>ppd->num_groups = %d\n"
1150 "<UL>\n", ppd->num_groups));
1151
1152 for (i = ppd->num_groups, group = ppd->groups; i > 0; i --, group ++)
1153 {
1154 DEBUG_printf(("<LI>%s<UL>\n", group->text));
1155
480ef0fe 1156 for (j = group->num_options, option = group->options;
1157 j > 0;
1158 j --, option ++)
ef416fc2 1159 if ((var = cgiGetVariable(option->keyword)) != NULL)
1160 {
1161 DEBUG_printf(("<LI>%s = \"%s\"</LI>\n", option->keyword, var));
1162 have_options = 1;
1163 ppdMarkOption(ppd, option->keyword, var);
1164 }
1165#ifdef DEBUG
1166 else
1167 printf("<LI>%s not defined!</LI>\n", option->keyword);
1168#endif /* DEBUG */
1169
1170 DEBUG_puts("</UL></LI>");
1171 }
1172
1173 DEBUG_printf(("</UL>\n"
1174 "<P>ppdConflicts(ppd) = %d\n", ppdConflicts(ppd)));
1175
1176 if (!have_options || ppdConflicts(ppd))
1177 {
1178 /*
1179 * Show the options to the user...
1180 */
1181
bd7854cb 1182 fputs("DEBUG: Showing options...\n", stderr);
1183
fa73b229 1184 ppdLocalize(ppd);
1185
89d46774 1186 cgiStartHTML(cgiText(_("Set Printer Options")));
ef416fc2 1187 cgiCopyTemplateLang("set-printer-options-header.tmpl");
1188
1189 if (ppdConflicts(ppd))
1190 {
480ef0fe 1191 for (i = ppd->num_groups, k = 0, group = ppd->groups;
1192 i > 0;
1193 i --, group ++)
1194 for (j = group->num_options, option = group->options;
1195 j > 0;
1196 j --, option ++)
ef416fc2 1197 if (option->conflicted)
1198 {
1199 cgiSetArray("ckeyword", k, option->keyword);
1200 cgiSetArray("ckeytext", k, option->text);
1201 k ++;
1202 }
1203
1204 cgiCopyTemplateLang("option-conflict.tmpl");
1205 }
1206
1207 for (i = ppd->num_groups, group = ppd->groups;
1208 i > 0;
1209 i --, group ++)
1210 {
1211 if (!strcmp(group->name, "InstallableOptions"))
fa73b229 1212 cgiSetVariable("GROUP", cgiText(_("Options Installed")));
ef416fc2 1213 else
1214 cgiSetVariable("GROUP", group->text);
1215
1216 cgiCopyTemplateLang("option-header.tmpl");
1217
1218 for (j = group->num_options, option = group->options;
1219 j > 0;
1220 j --, option ++)
1221 {
1222 if (!strcmp(option->keyword, "PageRegion"))
1223 continue;
1224
1225 cgiSetVariable("KEYWORD", option->keyword);
1226 cgiSetVariable("KEYTEXT", option->text);
1227
1228 if (option->conflicted)
1229 cgiSetVariable("CONFLICTED", "1");
1230 else
1231 cgiSetVariable("CONFLICTED", "0");
1232
1233 cgiSetSize("CHOICES", 0);
1234 cgiSetSize("TEXT", 0);
1235 for (k = 0, m = 0; k < option->num_choices; k ++)
1236 {
1237 /*
1238 * Hide custom option values...
1239 */
1240
1241 if (!strcmp(option->choices[k].choice, "Custom"))
1242 continue;
1243
1244 cgiSetArray("CHOICES", m, option->choices[k].choice);
1245 cgiSetArray("TEXT", m, option->choices[k].text);
1246
1247 m ++;
1248
1249 if (option->choices[k].marked)
1250 cgiSetVariable("DEFCHOICE", option->choices[k].choice);
1251 }
1252
1253 switch (option->ui)
1254 {
1255 case PPD_UI_BOOLEAN :
1256 cgiCopyTemplateLang("option-boolean.tmpl");
1257 break;
1258 case PPD_UI_PICKONE :
1259 cgiCopyTemplateLang("option-pickone.tmpl");
1260 break;
1261 case PPD_UI_PICKMANY :
1262 cgiCopyTemplateLang("option-pickmany.tmpl");
1263 break;
1264 }
1265 }
1266
1267 cgiCopyTemplateLang("option-trailer.tmpl");
1268 }
1269
1270 /*
1271 * Build an IPP_GET_PRINTER_ATTRIBUTES request, which requires the
1272 * following attributes:
1273 *
1274 * attributes-charset
1275 * attributes-natural-language
1276 * printer-uri
1277 */
1278
fa73b229 1279 request = ippNewRequest(IPP_GET_PRINTER_ATTRIBUTES);
ef416fc2 1280
a4d04587 1281 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
1282 "localhost", 0, "/printers/%s", printer);
ef416fc2 1283 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
1284 NULL, uri);
1285
1286 /*
1287 * Do the request and get back a response...
1288 */
1289
1290 if ((response = cupsDoRequest(http, request, "/")) != NULL)
1291 {
fa73b229 1292 if ((attr = ippFindAttribute(response, "job-sheets-supported",
1293 IPP_TAG_ZERO)) != NULL)
ef416fc2 1294 {
1295 /*
1296 * Add the job sheets options...
1297 */
1298
fa73b229 1299 cgiSetVariable("GROUP", cgiText(_("Banners")));
ef416fc2 1300 cgiCopyTemplateLang("option-header.tmpl");
1301
1302 cgiSetSize("CHOICES", attr->num_values);
1303 cgiSetSize("TEXT", attr->num_values);
1304 for (k = 0; k < attr->num_values; k ++)
1305 {
1306 cgiSetArray("CHOICES", k, attr->values[k].string.text);
1307 cgiSetArray("TEXT", k, attr->values[k].string.text);
1308 }
1309
1310 attr = ippFindAttribute(response, "job-sheets-default", IPP_TAG_ZERO);
1311
1312 cgiSetVariable("KEYWORD", "job_sheets_start");
fa73b229 1313 cgiSetVariable("KEYTEXT", cgiText(_("Starting Banner")));
ef416fc2 1314 cgiSetVariable("DEFCHOICE", attr == NULL ?
1315 "" : attr->values[0].string.text);
1316
1317 cgiCopyTemplateLang("option-pickone.tmpl");
1318
1319 cgiSetVariable("KEYWORD", "job_sheets_end");
fa73b229 1320 cgiSetVariable("KEYTEXT", cgiText(_("Ending Banner")));
ef416fc2 1321 cgiSetVariable("DEFCHOICE", attr == NULL && attr->num_values > 1 ?
1322 "" : attr->values[1].string.text);
1323
1324 cgiCopyTemplateLang("option-pickone.tmpl");
1325
1326 cgiCopyTemplateLang("option-trailer.tmpl");
1327 }
1328
1329 if (ippFindAttribute(response, "printer-error-policy-supported",
1330 IPP_TAG_ZERO) ||
1331 ippFindAttribute(response, "printer-op-policy-supported",
1332 IPP_TAG_ZERO))
1333 {
1334 /*
1335 * Add the error and operation policy options...
1336 */
1337
fa73b229 1338 cgiSetVariable("GROUP", cgiText(_("Policies")));
ef416fc2 1339 cgiCopyTemplateLang("option-header.tmpl");
1340
1341 /*
1342 * Error policy...
1343 */
1344
1345 attr = ippFindAttribute(response, "printer-error-policy-supported",
1346 IPP_TAG_ZERO);
1347
1348 if (attr)
1349 {
1350 cgiSetSize("CHOICES", attr->num_values);
1351 cgiSetSize("TEXT", attr->num_values);
1352 for (k = 0; k < attr->num_values; k ++)
1353 {
1354 cgiSetArray("CHOICES", k, attr->values[k].string.text);
1355 cgiSetArray("TEXT", k, attr->values[k].string.text);
1356 }
1357
1358 attr = ippFindAttribute(response, "printer-error-policy",
1359 IPP_TAG_ZERO);
1360
1361 cgiSetVariable("KEYWORD", "printer_error_policy");
fa73b229 1362 cgiSetVariable("KEYTEXT", cgiText(_("Error Policy")));
ef416fc2 1363 cgiSetVariable("DEFCHOICE", attr == NULL ?
1364 "" : attr->values[0].string.text);
1365 }
1366
1367 cgiCopyTemplateLang("option-pickone.tmpl");
1368
1369 /*
1370 * Operation policy...
1371 */
1372
1373 attr = ippFindAttribute(response, "printer-op-policy-supported",
1374 IPP_TAG_ZERO);
1375
1376 if (attr)
1377 {
1378 cgiSetSize("CHOICES", attr->num_values);
1379 cgiSetSize("TEXT", attr->num_values);
1380 for (k = 0; k < attr->num_values; k ++)
1381 {
1382 cgiSetArray("CHOICES", k, attr->values[k].string.text);
1383 cgiSetArray("TEXT", k, attr->values[k].string.text);
1384 }
1385
1386 attr = ippFindAttribute(response, "printer-op-policy", IPP_TAG_ZERO);
1387
1388 cgiSetVariable("KEYWORD", "printer_op_policy");
fa73b229 1389 cgiSetVariable("KEYTEXT", cgiText(_("Operation Policy")));
ef416fc2 1390 cgiSetVariable("DEFCHOICE", attr == NULL ?
1391 "" : attr->values[0].string.text);
1392
1393 cgiCopyTemplateLang("option-pickone.tmpl");
1394 }
1395
1396 cgiCopyTemplateLang("option-trailer.tmpl");
1397 }
1398
1399 ippDelete(response);
1400 }
1401
1402 /*
1403 * Binary protocol support...
1404 */
1405
1406 if (ppd->protocols && strstr(ppd->protocols, "BCP"))
1407 {
1408 protocol = ppdFindAttr(ppd, "cupsProtocol", NULL);
1409
fa73b229 1410 cgiSetVariable("GROUP", cgiText(_("PS Binary Protocol")));
ef416fc2 1411 cgiCopyTemplateLang("option-header.tmpl");
1412
1413 cgiSetSize("CHOICES", 2);
1414 cgiSetSize("TEXT", 2);
1415 cgiSetArray("CHOICES", 0, "None");
fa73b229 1416 cgiSetArray("TEXT", 0, cgiText(_("None")));
ef416fc2 1417
1418 if (strstr(ppd->protocols, "TBCP"))
1419 {
1420 cgiSetArray("CHOICES", 1, "TBCP");
1421 cgiSetArray("TEXT", 1, "TBCP");
1422 }
1423 else
1424 {
1425 cgiSetArray("CHOICES", 1, "BCP");
1426 cgiSetArray("TEXT", 1, "BCP");
1427 }
1428
1429 cgiSetVariable("KEYWORD", "protocol");
fa73b229 1430 cgiSetVariable("KEYTEXT", cgiText(_("PS Binary Protocol")));
ef416fc2 1431 cgiSetVariable("DEFCHOICE", protocol ? protocol->value : "None");
1432
1433 cgiCopyTemplateLang("option-pickone.tmpl");
1434
1435 cgiCopyTemplateLang("option-trailer.tmpl");
1436 }
1437
1438 cgiCopyTemplateLang("set-printer-options-trailer.tmpl");
1439 cgiEndHTML();
1440 }
1441 else
1442 {
1443 /*
1444 * Set default options...
1445 */
1446
bd7854cb 1447 fputs("DEBUG: Setting options...\n", stderr);
1448
ef416fc2 1449 out = cupsTempFile2(tempfile, sizeof(tempfile));
1450 in = cupsFileOpen(filename, "r");
1451
1452 if (!in || !out)
1453 {
1454 cgiSetVariable("ERROR", strerror(errno));
89d46774 1455 cgiStartHTML(cgiText(_("Set Printer Options")));
ef416fc2 1456 cgiCopyTemplateLang("error.tmpl");
1457 cgiEndHTML();
1458
1459 if (in)
1460 cupsFileClose(in);
1461
1462 if (out)
1463 {
1464 cupsFileClose(out);
1465 unlink(tempfile);
1466 }
1467
1468 unlink(filename);
1469 return;
1470 }
1471
1472 while (cupsFileGets(in, line, sizeof(line)))
1473 {
1474 if (!strncmp(line, "*cupsProtocol:", 14) && cgiGetVariable("protocol"))
1475 continue;
1476 else if (strncmp(line, "*Default", 8))
1477 cupsFilePrintf(out, "%s\n", line);
1478 else
1479 {
1480 /*
1481 * Get default option name...
1482 */
1483
1484 strlcpy(keyword, line + 8, sizeof(keyword));
1485
1486 for (keyptr = keyword; *keyptr; keyptr ++)
1487 if (*keyptr == ':' || isspace(*keyptr & 255))
1488 break;
1489
1490 *keyptr = '\0';
1491
f301802f 1492 if (!strcmp(keyword, "PageRegion") ||
1493 !strcmp(keyword, "PaperDimension") ||
1494 !strcmp(keyword, "ImageableArea"))
ef416fc2 1495 var = cgiGetVariable("PageSize");
1496 else
1497 var = cgiGetVariable(keyword);
1498
1499 if (var != NULL)
1500 cupsFilePrintf(out, "*Default%s: %s\n", keyword, var);
1501 else
1502 cupsFilePrintf(out, "%s\n", line);
1503 }
1504 }
1505
1506 if ((var = cgiGetVariable("protocol")) != NULL)
1507 cupsFilePrintf(out, "*cupsProtocol: %s\n", cgiGetVariable("protocol"));
1508
1509 cupsFileClose(in);
1510 cupsFileClose(out);
1511
1512 /*
1513 * Build a CUPS_ADD_PRINTER request, which requires the following
1514 * attributes:
1515 *
1516 * attributes-charset
1517 * attributes-natural-language
1518 * printer-uri
1519 * job-sheets-default
1520 * [ppd file]
1521 */
1522
fa73b229 1523 request = ippNewRequest(CUPS_ADD_PRINTER);
ef416fc2 1524
a4d04587 1525 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
1526 "localhost", 0, "/printers/%s",
1527 cgiGetVariable("PRINTER_NAME"));
ef416fc2 1528 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
1529 NULL, uri);
1530
1531 attr = ippAddStrings(request, IPP_TAG_PRINTER, IPP_TAG_NAME,
1532 "job-sheets-default", 2, NULL, NULL);
1533 attr->values[0].string.text = strdup(cgiGetVariable("job_sheets_start"));
1534 attr->values[1].string.text = strdup(cgiGetVariable("job_sheets_end"));
1535
1536 if ((var = cgiGetVariable("printer_error_policy")) != NULL)
1537 attr = ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_NAME,
1538 "printer-error-policy", NULL, var);
1539
1540 if ((var = cgiGetVariable("printer_op_policy")) != NULL)
1541 attr = ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_NAME,
1542 "printer-op-policy", NULL, var);
1543
1544 /*
1545 * Do the request and get back a response...
1546 */
1547
fa73b229 1548 ippDelete(cupsDoFileRequest(http, request, "/admin/", tempfile));
ef416fc2 1549
fa73b229 1550 if (cupsLastError() > IPP_OK_CONFLICT)
ef416fc2 1551 {
fa73b229 1552 cgiStartHTML(title);
1553 cgiShowIPPError(_("Unable to set options:"));
ef416fc2 1554 }
1555 else
1556 {
1557 /*
1558 * Redirect successful updates back to the printer page...
1559 */
1560
1561 char refresh[1024]; /* Refresh URL */
1562
fa73b229 1563
ef416fc2 1564 cgiFormEncode(uri, printer, sizeof(uri));
480ef0fe 1565 snprintf(refresh, sizeof(refresh),
f301802f 1566 "5;URL=/admin/?OP=redirect&URL=/printers/%s", uri);
ef416fc2 1567 cgiSetVariable("refresh_page", refresh);
1568
fa73b229 1569 cgiStartHTML(title);
ef416fc2 1570
1571 cgiCopyTemplateLang("printer-configured.tmpl");
1572 }
1573
1574 cgiEndHTML();
1575
1576 unlink(tempfile);
1577 }
1578
1579 unlink(filename);
1580}
1581
1582
1583/*
1584 * 'do_config_server()' - Configure server settings.
1585 */
1586
1587static void
fa73b229 1588do_config_server(http_t *http) /* I - HTTP connection */
ef416fc2 1589{
1590 if (cgiIsPOST() && !cgiGetVariable("CUPSDCONF"))
1591 {
1592 /*
1593 * Save basic setting changes...
1594 */
1595
757d2cad 1596 int num_settings; /* Number of server settings */
1597 cups_option_t *settings; /* Server settings */
1598
1599
1600 num_settings = 0;
1601 num_settings = cupsAddOption(CUPS_SERVER_DEBUG_LOGGING,
1602 cgiGetVariable("DEBUG_LOGGING") ? "1" : "0",
1603 num_settings, &settings);
1604 num_settings = cupsAddOption(CUPS_SERVER_REMOTE_ADMIN,
1605 cgiGetVariable("REMOTE_ADMIN") ? "1" : "0",
1606 num_settings, &settings);
1607 num_settings = cupsAddOption(CUPS_SERVER_REMOTE_PRINTERS,
1608 cgiGetVariable("REMOTE_PRINTERS") ? "1" : "0",
1609 num_settings, &settings);
1610 num_settings = cupsAddOption(CUPS_SERVER_SHARE_PRINTERS,
1611 cgiGetVariable("SHARE_PRINTERS") ? "1" : "0",
1612 num_settings, &settings);
1613 num_settings = cupsAddOption(CUPS_SERVER_USER_CANCEL_ANY,
1614 cgiGetVariable("USER_CANCEL_ANY") ? "1" : "0",
1615 num_settings, &settings);
1616
1617
1618 if (!_cupsAdminSetServerSettings(http, num_settings, settings))
ef416fc2 1619 {
fa73b229 1620 cgiStartHTML(cgiText(_("Change Settings")));
480ef0fe 1621 cgiSetVariable("MESSAGE",
1622 cgiText(_("Unable to change server settings:")));
757d2cad 1623 cgiSetVariable("ERROR", cupsLastErrorString());
ef416fc2 1624 cgiCopyTemplateLang("error.tmpl");
1625 }
1626 else
1627 {
f301802f 1628 cgiSetVariable("refresh_page", "5;URL=/admin/?OP=redirect");
fa73b229 1629 cgiStartHTML(cgiText(_("Change Settings")));
ef416fc2 1630 cgiCopyTemplateLang("restart.tmpl");
1631 }
1632
757d2cad 1633 cupsFreeOptions(num_settings, settings);
ef416fc2 1634
757d2cad 1635 cgiEndHTML();
ef416fc2 1636 }
1637 else if (cgiIsPOST())
1638 {
1639 /*
1640 * Save hand-edited config file...
1641 */
1642
1643 http_status_t status; /* PUT status */
1644 char tempfile[1024]; /* Temporary new cupsd.conf */
1645 int tempfd; /* Temporary file descriptor */
1646 cups_file_t *temp; /* Temporary file */
1647 const char *start, /* Start of line */
1648 *end; /* End of line */
1649
1650
1651 /*
1652 * Create a temporary file for the new cupsd.conf file...
1653 */
1654
1655 if ((tempfd = cupsTempFd(tempfile, sizeof(tempfile))) < 0)
1656 {
fa73b229 1657 cgiStartHTML(cgiText(_("Edit Configuration File")));
1658 cgiSetVariable("MESSAGE", cgiText(_("Unable to create temporary file:")));
ef416fc2 1659 cgiSetVariable("ERROR", strerror(errno));
1660 cgiCopyTemplateLang("error.tmpl");
1661 cgiEndHTML();
1662
1663 perror(tempfile);
1664 return;
1665 }
1666
1667 if ((temp = cupsFileOpenFd(tempfd, "w")) == NULL)
1668 {
fa73b229 1669 cgiStartHTML(cgiText(_("Edit Configuration File")));
1670 cgiSetVariable("MESSAGE", cgiText(_("Unable to create temporary file:")));
ef416fc2 1671 cgiSetVariable("ERROR", strerror(errno));
1672 cgiCopyTemplateLang("error.tmpl");
1673 cgiEndHTML();
1674
1675 perror(tempfile);
1676 close(tempfd);
1677 unlink(tempfile);
1678 return;
1679 }
1680
1681 /*
1682 * Copy the cupsd.conf text from the form variable...
1683 */
1684
1685 start = cgiGetVariable("CUPSDCONF");
1686 while (start)
1687 {
1688 if ((end = strstr(start, "\r\n")) == NULL)
1689 if ((end = strstr(start, "\n")) == NULL)
1690 end = start + strlen(start);
1691
1692 cupsFileWrite(temp, start, end - start);
1693 cupsFilePutChar(temp, '\n');
1694
1695 if (*end == '\r')
1696 start = end + 2;
1697 else if (*end == '\n')
1698 start = end + 1;
1699 else
1700 start = NULL;
1701 }
1702
1703 cupsFileClose(temp);
1704
1705 /*
1706 * Upload the configuration file to the server...
1707 */
1708
1709 status = cupsPutFile(http, "/admin/conf/cupsd.conf", tempfile);
1710
1711 if (status != HTTP_CREATED)
1712 {
480ef0fe 1713 cgiSetVariable("MESSAGE",
1714 cgiText(_("Unable to upload cupsd.conf file:")));
ef416fc2 1715 cgiSetVariable("ERROR", httpStatus(status));
fa73b229 1716
1717 cgiStartHTML(cgiText(_("Edit Configuration File")));
ef416fc2 1718 cgiCopyTemplateLang("error.tmpl");
1719 }
1720 else
1721 {
f301802f 1722 cgiSetVariable("refresh_page", "5;URL=/admin/?OP=redirect");
ef416fc2 1723
fa73b229 1724 cgiStartHTML(cgiText(_("Edit Configuration File")));
ef416fc2 1725 cgiCopyTemplateLang("restart.tmpl");
1726 }
1727
1728 cgiEndHTML();
1729
1730 unlink(tempfile);
1731 }
1732 else
1733 {
1734 struct stat info; /* cupsd.conf information */
1735 cups_file_t *cupsd; /* cupsd.conf file */
1736 char *buffer; /* Buffer for entire file */
1737 char filename[1024]; /* Filename */
1738 const char *server_root; /* Location of config files */
1739
1740
1741 /*
1742 * Locate the cupsd.conf file...
1743 */
1744
1745 if ((server_root = getenv("CUPS_SERVERROOT")) == NULL)
1746 server_root = CUPS_SERVERROOT;
1747
1748 snprintf(filename, sizeof(filename), "%s/cupsd.conf", server_root);
1749
1750 /*
1751 * Figure out the size...
1752 */
1753
1754 if (stat(filename, &info))
1755 {
fa73b229 1756 cgiStartHTML(cgiText(_("Edit Configuration File")));
480ef0fe 1757 cgiSetVariable("MESSAGE",
1758 cgiText(_("Unable to access cupsd.conf file:")));
ef416fc2 1759 cgiSetVariable("ERROR", strerror(errno));
1760 cgiCopyTemplateLang("error.tmpl");
1761 cgiEndHTML();
1762
1763 perror(filename);
1764 return;
1765 }
1766
1767 if (info.st_size > (1024 * 1024))
1768 {
fa73b229 1769 cgiStartHTML(cgiText(_("Edit Configuration File")));
480ef0fe 1770 cgiSetVariable("MESSAGE",
1771 cgiText(_("Unable to access cupsd.conf file:")));
fa73b229 1772 cgiSetVariable("ERROR",
1773 cgiText(_("Unable to edit cupsd.conf files larger than "
1774 "1MB!")));
ef416fc2 1775 cgiCopyTemplateLang("error.tmpl");
1776 cgiEndHTML();
1777
1778 fprintf(stderr, "ERROR: \"%s\" too large (%ld) to edit!\n", filename,
1779 (long)info.st_size);
1780 return;
1781 }
1782
1783 /*
1784 * Open the cupsd.conf file...
1785 */
1786
1787 if ((cupsd = cupsFileOpen(filename, "r")) == NULL)
1788 {
1789 /*
1790 * Unable to open - log an error...
1791 */
1792
fa73b229 1793 cgiStartHTML(cgiText(_("Edit Configuration File")));
480ef0fe 1794 cgiSetVariable("MESSAGE",
1795 cgiText(_("Unable to access cupsd.conf file:")));
ef416fc2 1796 cgiSetVariable("ERROR", strerror(errno));
1797 cgiCopyTemplateLang("error.tmpl");
1798 cgiEndHTML();
1799
1800 perror(filename);
1801 return;
1802 }
1803
1804 /*
1805 * Allocate memory and load the file into a string buffer...
1806 */
1807
1808 buffer = calloc(1, info.st_size + 1);
1809
1810 cupsFileRead(cupsd, buffer, info.st_size);
1811 cupsFileClose(cupsd);
1812
1813 cgiSetVariable("CUPSDCONF", buffer);
1814 free(buffer);
1815
1816 /*
1817 * Show the current config file...
1818 */
1819
89d46774 1820 cgiStartHTML(cgiText(_("Edit Configuration File")));
ef416fc2 1821
1822 printf("<!-- \"%s\" -->\n", filename);
1823
1824 cgiCopyTemplateLang("edit-config.tmpl");
1825
1826 cgiEndHTML();
1827 }
1828}
1829
1830
1831/*
1832 * 'do_delete_class()' - Delete a class...
1833 */
1834
1835static void
fa73b229 1836do_delete_class(http_t *http) /* I - HTTP connection */
ef416fc2 1837{
fa73b229 1838 ipp_t *request; /* IPP request */
ef416fc2 1839 char uri[HTTP_MAX_URI]; /* Job URI */
1840 const char *pclass; /* Printer class name */
ef416fc2 1841
1842
89d46774 1843 /*
1844 * Get form variables...
1845 */
fa73b229 1846
ef416fc2 1847 if (cgiGetVariable("CONFIRM") == NULL)
1848 {
89d46774 1849 cgiStartHTML(cgiText(_("Delete Class")));
ef416fc2 1850 cgiCopyTemplateLang("class-confirm.tmpl");
1851 cgiEndHTML();
1852 return;
1853 }
1854
1855 if ((pclass = cgiGetVariable("PRINTER_NAME")) != NULL)
a4d04587 1856 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
1857 "localhost", 0, "/classes/%s", pclass);
ef416fc2 1858 else
1859 {
89d46774 1860 cgiStartHTML(cgiText(_("Delete Class")));
fa73b229 1861 cgiSetVariable("ERROR", cgiText(_("Missing form variable!")));
ef416fc2 1862 cgiCopyTemplateLang("error.tmpl");
1863 cgiEndHTML();
1864 return;
1865 }
1866
1867 /*
1868 * Build a CUPS_DELETE_CLASS request, which requires the following
1869 * attributes:
1870 *
1871 * attributes-charset
1872 * attributes-natural-language
1873 * printer-uri
1874 */
1875
fa73b229 1876 request = ippNewRequest(CUPS_DELETE_CLASS);
ef416fc2 1877
1878 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
1879 NULL, uri);
1880
1881 /*
1882 * Do the request and get back a response...
1883 */
1884
fa73b229 1885 ippDelete(cupsDoRequest(http, request, "/admin/"));
ef416fc2 1886
89d46774 1887 /*
1888 * Show the results...
1889 */
1890
1891 cgiStartHTML(cgiText(_("Delete Class")));
1892
fa73b229 1893 if (cupsLastError() > IPP_OK_CONFLICT)
1894 cgiShowIPPError(_("Unable to delete class:"));
ef416fc2 1895 else
1896 cgiCopyTemplateLang("class-deleted.tmpl");
1897
1898 cgiEndHTML();
1899}
1900
1901
1902/*
1903 * 'do_delete_printer()' - Delete a printer...
1904 */
1905
1906static void
fa73b229 1907do_delete_printer(http_t *http) /* I - HTTP connection */
ef416fc2 1908{
fa73b229 1909 ipp_t *request; /* IPP request */
ef416fc2 1910 char uri[HTTP_MAX_URI]; /* Job URI */
1911 const char *printer; /* Printer printer name */
ef416fc2 1912
1913
89d46774 1914 /*
1915 * Get form variables...
1916 */
fa73b229 1917
ef416fc2 1918 if (cgiGetVariable("CONFIRM") == NULL)
1919 {
89d46774 1920 cgiStartHTML(cgiText(_("Delete Printer")));
ef416fc2 1921 cgiCopyTemplateLang("printer-confirm.tmpl");
1922 cgiEndHTML();
1923 return;
1924 }
1925
1926 if ((printer = cgiGetVariable("PRINTER_NAME")) != NULL)
a4d04587 1927 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
1928 "localhost", 0, "/printers/%s", printer);
ef416fc2 1929 else
1930 {
89d46774 1931 cgiStartHTML(cgiText(_("Delete Printer")));
fa73b229 1932 cgiSetVariable("ERROR", cgiText(_("Missing form variable!")));
ef416fc2 1933 cgiCopyTemplateLang("error.tmpl");
1934 cgiEndHTML();
1935 return;
1936 }
1937
1938 /*
1939 * Build a CUPS_DELETE_PRINTER request, which requires the following
1940 * attributes:
1941 *
1942 * attributes-charset
1943 * attributes-natural-language
1944 * printer-uri
1945 */
1946
fa73b229 1947 request = ippNewRequest(CUPS_DELETE_PRINTER);
ef416fc2 1948
1949 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
1950 NULL, uri);
1951
1952 /*
1953 * Do the request and get back a response...
1954 */
1955
fa73b229 1956 ippDelete(cupsDoRequest(http, request, "/admin/"));
1957
89d46774 1958 /*
1959 * Show the results...
1960 */
1961
1962 cgiStartHTML(cgiText(_("Delete Printer")));
1963
fa73b229 1964 if (cupsLastError() > IPP_OK_CONFLICT)
1965 cgiShowIPPError(_("Unable to delete printer:"));
1966 else
1967 cgiCopyTemplateLang("printer-deleted.tmpl");
1968
1969 cgiEndHTML();
1970}
1971
1972
1973/*
1974 * 'do_export()' - Export printers to Samba...
1975 */
1976
1977static void
1978do_export(http_t *http) /* I - HTTP connection */
1979{
1980 int i, j; /* Looping vars */
1981 ipp_t *request, /* IPP request */
1982 *response; /* IPP response */
1983 const char *username, /* Samba username */
1984 *password, /* Samba password */
1985 *export_all; /* Export all printers? */
1986 int export_count, /* Number of printers to export */
1987 printer_count; /* Number of available printers */
757d2cad 1988 const char *name, /* What name to pull */
1989 *dest; /* Current destination */
1990 char ppd[1024]; /* PPD file */
fa73b229 1991
1992
fa73b229 1993 /*
1994 * Get form data...
1995 */
1996
1997 username = cgiGetVariable("USERNAME");
1998 password = cgiGetVariable("PASSWORD");
1999 export_all = cgiGetVariable("EXPORT_ALL");
2000 export_count = cgiGetSize("EXPORT_NAME");
2001
fa73b229 2002 /*
2003 * Get list of available printers...
2004 */
ef416fc2 2005
fa73b229 2006 cgiSetSize("PRINTER_NAME", 0);
2007 cgiSetSize("PRINTER_EXPORT", 0);
ef416fc2 2008
fa73b229 2009 request = ippNewRequest(CUPS_GET_PRINTERS);
2010
2011 ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_ENUM,
2012 "printer-type", 0);
2013
2014 ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_ENUM,
2015 "printer-type-mask", CUPS_PRINTER_CLASS | CUPS_PRINTER_REMOTE |
2016 CUPS_PRINTER_IMPLICIT);
2017
2018 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
2019 "requested-attributes", NULL, "printer-name");
2020
2021 if ((response = cupsDoRequest(http, request, "/")) != NULL)
ef416fc2 2022 {
fa73b229 2023 cgiSetIPPVars(response, NULL, NULL, NULL, 0);
2024 ippDelete(response);
2025
2026 if (!export_all)
2027 {
2028 printer_count = cgiGetSize("PRINTER_NAME");
2029
2030 for (i = 0; i < printer_count; i ++)
2031 {
757d2cad 2032 dest = cgiGetArray("PRINTER_NAME", i);
2033
fa73b229 2034 for (j = 0; j < export_count; j ++)
757d2cad 2035 if (!strcasecmp(dest, cgiGetArray("EXPORT_NAME", j)))
fa73b229 2036 break;
2037
2038 cgiSetArray("PRINTER_EXPORT", i, j < export_count ? "Y" : "");
2039 }
2040 }
ef416fc2 2041 }
ef416fc2 2042
757d2cad 2043 /*
2044 * Export or get the printers to export...
2045 */
2046
2047 if (username && *username && password && *password &&
2048 (export_all || export_count > 0))
2049 {
2050 /*
2051 * Do export...
2052 */
2053
2054 fputs("DEBUG: Export printers...\n", stderr);
2055
2056 if (export_all)
2057 {
2058 name = "PRINTER_NAME";
2059 export_count = cgiGetSize("PRINTER_NAME");
2060 }
2061 else
2062 name = "EXPORT_NAME";
2063
2064 for (i = 0; i < export_count; i ++)
2065 {
2066 dest = cgiGetArray(name, i);
2067
2068 if (!cupsAdminCreateWindowsPPD(http, dest, ppd, sizeof(ppd)))
2069 break;
2070
2071 j = cupsAdminExportSamba(dest, ppd, "localhost", username, password,
2072 stderr);
2073
2074 unlink(ppd);
2075
2076 if (!j)
2077 break;
2078 }
2079
2080 if (i < export_count)
2081 cgiSetVariable("ERROR", cupsLastErrorString());
2082 else
2083 {
2084 cgiStartHTML(cgiText(_("Export Printers to Samba")));
2085 cgiCopyTemplateLang("samba-exported.tmpl");
2086 cgiEndHTML();
2087 return;
2088 }
2089 }
2090 else if (username && !*username)
2091 cgiSetVariable("ERROR",
2092 cgiText(_("A Samba username is required to export "
2093 "printer drivers!")));
2094 else if (username && (!password || !*password))
2095 cgiSetVariable("ERROR",
2096 cgiText(_("A Samba password is required to export "
2097 "printer drivers!")));
2098
fa73b229 2099 /*
2100 * Show form...
2101 */
2102
757d2cad 2103 cgiStartHTML(cgiText(_("Export Printers to Samba")));
fa73b229 2104 cgiCopyTemplateLang("samba-export.tmpl");
ef416fc2 2105 cgiEndHTML();
2106}
2107
2108
2109/*
2110 * 'do_menu()' - Show the main menu...
2111 */
2112
2113static void
fa73b229 2114do_menu(http_t *http) /* I - HTTP connection */
ef416fc2 2115{
757d2cad 2116 int num_settings; /* Number of server settings */
2117 cups_option_t *settings; /* Server settings */
2118 const char *val; /* Setting value */
2119 char filename[1024]; /* Temporary filename */
fa73b229 2120 const char *datadir; /* Location of data files */
ef416fc2 2121 ipp_t *request, /* IPP request */
2122 *response; /* IPP response */
2123 ipp_attribute_t *attr; /* IPP attribute */
2124
2125
2126 /*
757d2cad 2127 * Get the current server settings...
ef416fc2 2128 */
2129
757d2cad 2130 if (!_cupsAdminGetServerSettings(http, &num_settings, &settings))
ef416fc2 2131 {
480ef0fe 2132 cgiSetVariable("SETTINGS_MESSAGE",
2133 cgiText(_("Unable to open cupsd.conf file:")));
2134 cgiSetVariable("SETTINGS_ERROR", cupsLastErrorString());
ef416fc2 2135 }
ef416fc2 2136
757d2cad 2137 if ((val = cupsGetOption(CUPS_SERVER_DEBUG_LOGGING, num_settings,
2138 settings)) != NULL && atoi(val))
2139 cgiSetVariable("DEBUG_LOGGING", "CHECKED");
ef416fc2 2140
757d2cad 2141 if ((val = cupsGetOption(CUPS_SERVER_REMOTE_ADMIN, num_settings,
2142 settings)) != NULL && atoi(val))
2143 cgiSetVariable("REMOTE_ADMIN", "CHECKED");
ef416fc2 2144
757d2cad 2145 if ((val = cupsGetOption(CUPS_SERVER_REMOTE_PRINTERS, num_settings,
2146 settings)) != NULL && atoi(val))
2147 cgiSetVariable("REMOTE_PRINTERS", "CHECKED");
ef416fc2 2148
757d2cad 2149 if ((val = cupsGetOption(CUPS_SERVER_SHARE_PRINTERS, num_settings,
2150 settings)) != NULL && atoi(val))
2151 cgiSetVariable("SHARE_PRINTERS", "CHECKED");
ef416fc2 2152
757d2cad 2153 if ((val = cupsGetOption(CUPS_SERVER_USER_CANCEL_ANY, num_settings,
2154 settings)) != NULL && atoi(val))
2155 cgiSetVariable("USER_CANCEL_ANY", "CHECKED");
ef416fc2 2156
480ef0fe 2157 cupsFreeOptions(num_settings, settings);
2158
ef416fc2 2159 /*
2160 * Get the list of printers and their devices...
2161 */
2162
fa73b229 2163 request = ippNewRequest(CUPS_GET_PRINTERS);
ef416fc2 2164
2165 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
2166 "requested-attributes", NULL, "device-uri");
2167
2168 ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_ENUM, "printer-type",
2169 CUPS_PRINTER_LOCAL);
2170 ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_ENUM, "printer-type-mask",
2171 CUPS_PRINTER_LOCAL);
2172
2173 if ((response = cupsDoRequest(http, request, "/")) != NULL)
2174 {
2175 /*
2176 * Got the printer list, now load the devices...
2177 */
2178
2179 int i; /* Looping var */
fa73b229 2180 cups_array_t *printer_devices; /* Printer devices for local printers */
2181 char *printer_device; /* Current printer device */
ef416fc2 2182
2183
2184 /*
fa73b229 2185 * Allocate an array and copy the device strings...
ef416fc2 2186 */
2187
fa73b229 2188 printer_devices = cupsArrayNew((cups_array_func_t)strcmp, NULL);
ef416fc2 2189
fa73b229 2190 for (attr = ippFindAttribute(response, "device-uri", IPP_TAG_URI);
2191 attr;
2192 attr = ippFindNextAttribute(response, "device-uri", IPP_TAG_URI))
ef416fc2 2193 {
fa73b229 2194 cupsArrayAdd(printer_devices, strdup(attr->values[0].string.text));
ef416fc2 2195 }
ef416fc2 2196
2197 /*
2198 * Free the printer list and get the device list...
2199 */
2200
2201 ippDelete(response);
2202
fa73b229 2203 request = ippNewRequest(CUPS_GET_DEVICES);
ef416fc2 2204
2205 if ((response = cupsDoRequest(http, request, "/")) != NULL)
2206 {
2207 /*
2208 * Got the device list, let's parse it...
2209 */
2210
2211 const char *device_uri, /* device-uri attribute value */
2212 *device_make_and_model, /* device-make-and-model value */
2213 *device_info; /* device-info value */
2214
2215
2216 for (i = 0, attr = response->attrs; attr; attr = attr->next)
2217 {
2218 /*
2219 * Skip leading attributes until we hit a device...
2220 */
2221
2222 while (attr && attr->group_tag != IPP_TAG_PRINTER)
2223 attr = attr->next;
2224
2225 if (!attr)
2226 break;
2227
2228 /*
2229 * Pull the needed attributes from this device...
2230 */
2231
2232 device_info = NULL;
2233 device_make_and_model = NULL;
2234 device_uri = NULL;
2235
2236 while (attr && attr->group_tag == IPP_TAG_PRINTER)
2237 {
fa73b229 2238 if (!strcmp(attr->name, "device-info") &&
ef416fc2 2239 attr->value_tag == IPP_TAG_TEXT)
2240 device_info = attr->values[0].string.text;
2241
fa73b229 2242 if (!strcmp(attr->name, "device-make-and-model") &&
ef416fc2 2243 attr->value_tag == IPP_TAG_TEXT)
2244 device_make_and_model = attr->values[0].string.text;
2245
fa73b229 2246 if (!strcmp(attr->name, "device-uri") &&
ef416fc2 2247 attr->value_tag == IPP_TAG_URI)
2248 device_uri = attr->values[0].string.text;
2249
2250 attr = attr->next;
2251 }
2252
2253 /*
2254 * See if we have everything needed...
2255 */
2256
2257 if (device_info && device_make_and_model && device_uri &&
2258 strcasecmp(device_make_and_model, "unknown") &&
2259 strchr(device_uri, ':'))
2260 {
2261 /*
2262 * Yes, now see if there is already a printer for this
2263 * device...
2264 */
2265
fa73b229 2266 if (!cupsArrayFind(printer_devices, (void *)device_uri))
ef416fc2 2267 {
2268 /*
2269 * Not found, so it must be a new printer...
2270 */
2271
2272 char options[1024], /* Form variables for this device */
2273 *options_ptr; /* Pointer into string */
2274 const char *ptr; /* Pointer into device string */
2275
2276
2277 /*
2278 * Format the printer name variable for this device...
2279 *
2280 * We use the device-info string first, then device-uri,
2281 * and finally device-make-and-model to come up with a
2282 * suitable name.
2283 */
2284
2285 strcpy(options, "PRINTER_NAME=");
2286 options_ptr = options + strlen(options);
2287
2288 if (strncasecmp(device_info, "unknown", 7))
2289 ptr = device_info;
2290 else if ((ptr = strstr(device_uri, "://")) != NULL)
2291 ptr += 3;
2292 else
2293 ptr = device_make_and_model;
2294
2295 for (;
2296 options_ptr < (options + sizeof(options) - 1) && *ptr;
2297 ptr ++)
480ef0fe 2298 if (isalnum(*ptr & 255) || *ptr == '_' || *ptr == '-' ||
2299 *ptr == '.')
ef416fc2 2300 *options_ptr++ = *ptr;
2301 else if ((*ptr == ' ' || *ptr == '/') && options_ptr[-1] != '_')
2302 *options_ptr++ = '_';
2303 else if (*ptr == '?' || *ptr == '(')
2304 break;
2305
2306 /*
2307 * Then add the make and model in the printer info, so
2308 * that MacOS clients see something reasonable...
2309 */
2310
2311 strlcpy(options_ptr, "&PRINTER_LOCATION=Local+Printer"
2312 "&PRINTER_INFO=",
2313 sizeof(options) - (options_ptr - options));
2314 options_ptr += strlen(options_ptr);
2315
2316 cgiFormEncode(options_ptr, device_make_and_model,
2317 sizeof(options) - (options_ptr - options));
2318 options_ptr += strlen(options_ptr);
2319
2320 /*
2321 * Then copy the device URI...
2322 */
2323
2324 strlcpy(options_ptr, "&DEVICE_URI=",
2325 sizeof(options) - (options_ptr - options));
2326 options_ptr += strlen(options_ptr);
2327
2328 cgiFormEncode(options_ptr, device_uri,
fa73b229 2329 sizeof(options) - (options_ptr - options));
ef416fc2 2330 options_ptr += strlen(options_ptr);
2331
2332 if (options_ptr < (options + sizeof(options) - 1))
2333 {
2334 *options_ptr++ = '|';
2335 cgiFormEncode(options_ptr, device_make_and_model,
2336 sizeof(options) - (options_ptr - options));
2337 }
2338
2339 /*
2340 * Finally, set the form variables for this printer...
2341 */
2342
2343 cgiSetArray("device_info", i, device_info);
2344 cgiSetArray("device_make_and_model", i, device_make_and_model);
2345 cgiSetArray("device_options", i, options);
2346 cgiSetArray("device_uri", i, device_uri);
2347 i ++;
2348 }
2349 }
2350
2351 if (!attr)
2352 break;
2353 }
2354
fa73b229 2355 ippDelete(response);
2356
ef416fc2 2357 /*
2358 * Free the device list...
2359 */
2360
fa73b229 2361 for (printer_device = (char *)cupsArrayFirst(printer_devices);
2362 printer_device;
2363 printer_device = (char *)cupsArrayNext(printer_devices))
2364 free(printer_device);
ef416fc2 2365
fa73b229 2366 cupsArrayDelete(printer_devices);
ef416fc2 2367 }
2368 }
2369
fa73b229 2370 /*
2371 * See if Samba and the Windows drivers are installed...
2372 */
2373
2374 if ((datadir = getenv("CUPS_DATADIR")) == NULL)
2375 datadir = CUPS_DATADIR;
2376
757d2cad 2377 snprintf(filename, sizeof(filename), "%s/drivers/pscript5.dll", datadir);
2378 if (!access(filename, R_OK))
fa73b229 2379 {
2380 /*
2381 * Found Windows 2000 driver file, see if we have smbclient and
2382 * rpcclient...
2383 */
2384
757d2cad 2385 if (cupsFileFind("smbclient", getenv("PATH"), 1, filename,
2386 sizeof(filename)) &&
2387 cupsFileFind("rpcclient", getenv("PATH"), 1, filename,
2388 sizeof(filename)))
fa73b229 2389 cgiSetVariable("HAVE_SAMBA", "Y");
2390 else
2391 {
757d2cad 2392 if (!cupsFileFind("smbclient", getenv("PATH"), 1, filename,
2393 sizeof(filename)))
fa73b229 2394 fputs("ERROR: smbclient not found!\n", stderr);
2395
757d2cad 2396 if (!cupsFileFind("rpcclient", getenv("PATH"), 1, filename,
2397 sizeof(filename)))
fa73b229 2398 fputs("ERROR: rpcclient not found!\n", stderr);
2399 }
2400 }
2401 else
757d2cad 2402 perror(filename);
fa73b229 2403
ef416fc2 2404 /*
2405 * Finally, show the main menu template...
2406 */
2407
757d2cad 2408 cgiStartHTML(cgiText(_("Administration")));
2409
ef416fc2 2410 cgiCopyTemplateLang("admin.tmpl");
2411
2412 cgiEndHTML();
2413}
2414
2415
2416/*
2417 * 'do_printer_op()' - Do a printer operation.
2418 */
2419
2420static void
2421do_printer_op(http_t *http, /* I - HTTP connection */
ef416fc2 2422 ipp_op_t op, /* I - Operation to perform */
2423 const char *title) /* I - Title of page */
2424{
fa73b229 2425 ipp_t *request; /* IPP request */
ef416fc2 2426 char uri[HTTP_MAX_URI]; /* Printer URI */
fa73b229 2427 const char *printer, /* Printer name (purge-jobs) */
2428 *is_class; /* Is a class? */
ef416fc2 2429
2430
fa73b229 2431 is_class = cgiGetVariable("IS_CLASS");
2432 printer = cgiGetVariable("PRINTER_NAME");
2433
2434 if (!printer)
ef416fc2 2435 {
fa73b229 2436 cgiSetVariable("ERROR", cgiText(_("Missing form variable!")));
ef416fc2 2437 cgiStartHTML(title);
2438 cgiCopyTemplateLang("error.tmpl");
2439 cgiEndHTML();
2440 return;
2441 }
2442
2443 /*
2444 * Build a printer request, which requires the following
2445 * attributes:
2446 *
2447 * attributes-charset
2448 * attributes-natural-language
2449 * printer-uri
2450 */
2451
fa73b229 2452 request = ippNewRequest(op);
ef416fc2 2453
a4d04587 2454 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
2455 "localhost", 0, is_class ? "/classes/%s" : "/printers/%s",
2456 printer);
ef416fc2 2457 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
2458 NULL, uri);
2459
2460 /*
2461 * Do the request and get back a response...
2462 */
2463
fa73b229 2464 ippDelete(cupsDoRequest(http, request, "/admin/"));
ef416fc2 2465
fa73b229 2466 if (cupsLastError() > IPP_OK_CONFLICT)
ef416fc2 2467 {
2468 cgiStartHTML(title);
fa73b229 2469 cgiShowIPPError(_("Unable to change printer:"));
ef416fc2 2470 }
2471 else
2472 {
2473 /*
2474 * Redirect successful updates back to the printer page...
2475 */
2476
fa73b229 2477 char url[1024], /* Printer/class URL */
2478 refresh[1024]; /* Refresh URL */
ef416fc2 2479
fa73b229 2480
2481 cgiRewriteURL(uri, url, sizeof(url), NULL);
2482 cgiFormEncode(uri, url, sizeof(uri));
f301802f 2483 snprintf(refresh, sizeof(refresh), "5;URL=/admin/?OP=redirect&URL=%s", uri);
ef416fc2 2484 cgiSetVariable("refresh_page", refresh);
2485
2486 cgiStartHTML(title);
2487
2488 if (op == IPP_PAUSE_PRINTER)
2489 cgiCopyTemplateLang("printer-stop.tmpl");
2490 else if (op == IPP_RESUME_PRINTER)
2491 cgiCopyTemplateLang("printer-start.tmpl");
2492 else if (op == CUPS_ACCEPT_JOBS)
2493 cgiCopyTemplateLang("printer-accept.tmpl");
2494 else if (op == CUPS_REJECT_JOBS)
2495 cgiCopyTemplateLang("printer-reject.tmpl");
2496 else if (op == IPP_PURGE_JOBS)
2497 cgiCopyTemplateLang("printer-purge.tmpl");
2498 else if (op == CUPS_SET_DEFAULT)
2499 cgiCopyTemplateLang("printer-default.tmpl");
2500 }
2501
2502 cgiEndHTML();
2503}
2504
2505
2506/*
2507 * 'do_set_allowed_users()' - Set the allowed/denied users for a queue.
2508 */
2509
2510static void
fa73b229 2511do_set_allowed_users(http_t *http) /* I - HTTP connection */
ef416fc2 2512{
2513 int i; /* Looping var */
2514 ipp_t *request, /* IPP request */
2515 *response; /* IPP response */
2516 char uri[HTTP_MAX_URI]; /* Printer URI */
2517 const char *printer, /* Printer name (purge-jobs) */
fa73b229 2518 *is_class, /* Is a class? */
ef416fc2 2519 *users, /* List of users or groups */
2520 *type; /* Allow/deny type */
2521 int num_users; /* Number of users */
2522 char *ptr, /* Pointer into users string */
2523 *end, /* Pointer to end of users string */
2524 quote; /* Quote character */
2525 ipp_attribute_t *attr; /* Attribute */
ef416fc2 2526 static const char * const attrs[] = /* Requested attributes */
2527 {
2528 "requesting-user-name-allowed",
2529 "requesting-user-name-denied"
2530 };
2531
2532
fa73b229 2533 is_class = cgiGetVariable("IS_CLASS");
2534 printer = cgiGetVariable("PRINTER_NAME");
2535
2536 if (!printer)
ef416fc2 2537 {
fa73b229 2538 cgiSetVariable("ERROR", cgiText(_("Missing form variable!")));
2539 cgiStartHTML(cgiText(_("Set Allowed Users")));
ef416fc2 2540 cgiCopyTemplateLang("error.tmpl");
2541 cgiEndHTML();
2542 return;
2543 }
2544
2545 users = cgiGetVariable("users");
2546 type = cgiGetVariable("type");
2547
2548 if (!users || !type ||
2549 (strcmp(type, "requesting-user-name-allowed") &&
2550 strcmp(type, "requesting-user-name-denied")))
2551 {
2552 /*
2553 * Build a Get-Printer-Attributes request, which requires the following
2554 * attributes:
2555 *
2556 * attributes-charset
2557 * attributes-natural-language
2558 * printer-uri
2559 * requested-attributes
2560 */
2561
fa73b229 2562 request = ippNewRequest(IPP_GET_PRINTER_ATTRIBUTES);
ef416fc2 2563
a4d04587 2564 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
2565 "localhost", 0, is_class ? "/classes/%s" : "/printers/%s",
2566 printer);
ef416fc2 2567 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
2568 NULL, uri);
2569
2570 ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
2571 "requested-attributes",
2572 (int)(sizeof(attrs) / sizeof(attrs[0])), NULL, attrs);
2573
2574 /*
2575 * Do the request and get back a response...
2576 */
2577
fa73b229 2578 if ((response = cupsDoRequest(http, request, "/")) != NULL)
ef416fc2 2579 {
ef416fc2 2580 cgiSetIPPVars(response, NULL, NULL, NULL, 0);
2581
2582 ippDelete(response);
2583 }
ef416fc2 2584
fa73b229 2585 cgiStartHTML(cgiText(_("Set Allowed Users")));
ef416fc2 2586
fa73b229 2587 if (cupsLastError() > IPP_OK_CONFLICT)
2588 cgiShowIPPError(_("Unable to get printer attributes:"));
ef416fc2 2589 else
2590 cgiCopyTemplateLang("users.tmpl");
2591
2592 cgiEndHTML();
2593 }
2594 else
2595 {
2596 /*
2597 * Save the changes...
2598 */
2599
2600 for (num_users = 0, ptr = (char *)users; *ptr; num_users ++)
2601 {
2602 /*
2603 * Skip whitespace and commas...
2604 */
2605
2606 while (*ptr == ',' || isspace(*ptr & 255))
2607 ptr ++;
2608
2609 if (*ptr == '\'' || *ptr == '\"')
2610 {
2611 /*
2612 * Scan quoted name...
2613 */
2614
2615 quote = *ptr++;
2616
2617 for (end = ptr; *end; end ++)
2618 if (*end == quote)
2619 break;
2620 }
2621 else
2622 {
2623 /*
2624 * Scan space or comma-delimited name...
2625 */
2626
2627 for (end = ptr; *end; end ++)
2628 if (isspace(*end & 255) || *end == ',')
2629 break;
2630 }
2631
2632 /*
2633 * Advance to the next name...
2634 */
2635
2636 ptr = end;
2637 }
2638
2639 /*
fa73b229 2640 * Build a CUPS-Add-Printer/Class request, which requires the following
ef416fc2 2641 * attributes:
2642 *
2643 * attributes-charset
2644 * attributes-natural-language
2645 * printer-uri
2646 * requesting-user-name-{allowed,denied}
2647 */
2648
fa73b229 2649 request = ippNewRequest(is_class ? CUPS_ADD_CLASS : CUPS_ADD_PRINTER);
ef416fc2 2650
a4d04587 2651 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
2652 "localhost", 0, is_class ? "/classes/%s" : "/printers/%s",
2653 printer);
ef416fc2 2654 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
2655 NULL, uri);
2656
2657 if (num_users == 0)
e1d6a774 2658 ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_NAME,
ef416fc2 2659 "requesting-user-name-allowed", NULL, "all");
2660 else
2661 {
e1d6a774 2662 attr = ippAddStrings(request, IPP_TAG_PRINTER, IPP_TAG_NAME,
ef416fc2 2663 type, num_users, NULL, NULL);
2664
2665 for (i = 0, ptr = (char *)users; *ptr; i ++)
2666 {
2667 /*
2668 * Skip whitespace and commas...
2669 */
2670
2671 while (*ptr == ',' || isspace(*ptr & 255))
2672 ptr ++;
2673
2674 if (*ptr == '\'' || *ptr == '\"')
2675 {
2676 /*
2677 * Scan quoted name...
2678 */
2679
2680 quote = *ptr++;
2681
2682 for (end = ptr; *end; end ++)
2683 if (*end == quote)
2684 break;
2685 }
2686 else
2687 {
2688 /*
2689 * Scan space or comma-delimited name...
2690 */
2691
2692 for (end = ptr; *end; end ++)
2693 if (isspace(*end & 255) || *end == ',')
2694 break;
2695 }
2696
2697 /*
2698 * Terminate the name...
2699 */
2700
2701 if (*end)
2702 *end++ = '\0';
2703
2704 /*
2705 * Add the name...
2706 */
2707
2708 attr->values[i].string.text = strdup(ptr);
2709
2710 /*
2711 * Advance to the next name...
2712 */
2713
2714 ptr = end;
2715 }
2716 }
2717
2718 /*
2719 * Do the request and get back a response...
2720 */
2721
fa73b229 2722 ippDelete(cupsDoRequest(http, request, "/admin/"));
ef416fc2 2723
fa73b229 2724 if (cupsLastError() > IPP_OK_CONFLICT)
ef416fc2 2725 {
fa73b229 2726 cgiStartHTML(cgiText(_("Set Allowed Users")));
2727 cgiShowIPPError(_("Unable to change printer:"));
ef416fc2 2728 }
2729 else
2730 {
2731 /*
2732 * Redirect successful updates back to the printer page...
2733 */
2734
fa73b229 2735 char url[1024], /* Printer/class URL */
2736 refresh[1024]; /* Refresh URL */
ef416fc2 2737
fa73b229 2738
2739 cgiRewriteURL(uri, url, sizeof(url), NULL);
2740 cgiFormEncode(uri, url, sizeof(uri));
f301802f 2741 snprintf(refresh, sizeof(refresh), "5;URL=/admin/?OP=redirect&URL=%s",
2742 uri);
ef416fc2 2743 cgiSetVariable("refresh_page", refresh);
2744
fa73b229 2745 cgiStartHTML(cgiText(_("Set Allowed Users")));
ef416fc2 2746
fa73b229 2747 cgiCopyTemplateLang(is_class ? "class-modified.tmpl" :
2748 "printer-modified.tmpl");
ef416fc2 2749 }
2750
2751 cgiEndHTML();
2752 }
2753}
2754
2755
2756/*
2757 * 'do_set_sharing()' - Set printer-is-shared value...
2758 */
2759
2760static void
fa73b229 2761do_set_sharing(http_t *http) /* I - HTTP connection */
ef416fc2 2762{
2763 ipp_t *request, /* IPP request */
2764 *response; /* IPP response */
2765 char uri[HTTP_MAX_URI]; /* Printer URI */
2766 const char *printer, /* Printer name */
fa73b229 2767 *is_class, /* Is a class? */
ef416fc2 2768 *shared; /* Sharing value */
ef416fc2 2769
2770
fa73b229 2771 is_class = cgiGetVariable("IS_CLASS");
2772 printer = cgiGetVariable("PRINTER_NAME");
2773 shared = cgiGetVariable("SHARED");
ef416fc2 2774
fa73b229 2775 if (!printer || !shared)
ef416fc2 2776 {
fa73b229 2777 cgiSetVariable("ERROR", cgiText(_("Missing form variable!")));
2778 cgiStartHTML(cgiText(_("Set Publishing")));
ef416fc2 2779 cgiCopyTemplateLang("error.tmpl");
2780 cgiEndHTML();
2781 return;
2782 }
2783
2784 /*
fa73b229 2785 * Build a CUPS-Add-Printer/CUPS-Add-Class request, which requires the
2786 * following attributes:
ef416fc2 2787 *
2788 * attributes-charset
2789 * attributes-natural-language
2790 * printer-uri
2791 * printer-is-shared
2792 */
2793
fa73b229 2794 request = ippNewRequest(is_class ? CUPS_ADD_CLASS : CUPS_ADD_PRINTER);
ef416fc2 2795
a4d04587 2796 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
2797 "localhost", 0, is_class ? "/classes/%s" : "/printers/%s",
2798 printer);
ef416fc2 2799 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
2800 NULL, uri);
2801
2802 ippAddBoolean(request, IPP_TAG_OPERATION, "printer-is-shared", atoi(shared));
2803
2804 /*
2805 * Do the request and get back a response...
2806 */
2807
2808 if ((response = cupsDoRequest(http, request, "/admin/")) != NULL)
2809 {
ef416fc2 2810 cgiSetIPPVars(response, NULL, NULL, NULL, 0);
2811
2812 ippDelete(response);
2813 }
ef416fc2 2814
fa73b229 2815 if (cupsLastError() > IPP_OK_CONFLICT)
ef416fc2 2816 {
fa73b229 2817 cgiStartHTML(cgiText(_("Set Publishing")));
2818 cgiShowIPPError(_("Unable to change printer-is-shared attribute:"));
ef416fc2 2819 }
2820 else
2821 {
2822 /*
2823 * Redirect successful updates back to the printer page...
2824 */
2825
fa73b229 2826 char url[1024], /* Printer/class URL */
2827 refresh[1024]; /* Refresh URL */
ef416fc2 2828
ef416fc2 2829
fa73b229 2830 cgiRewriteURL(uri, url, sizeof(url), NULL);
2831 cgiFormEncode(uri, url, sizeof(uri));
f301802f 2832 snprintf(refresh, sizeof(refresh), "5;URL=/admin/?OP=redirect&URL=%s", uri);
fa73b229 2833 cgiSetVariable("refresh_page", refresh);
ef416fc2 2834
fa73b229 2835 cgiStartHTML(cgiText(_("Set Publishing")));
2836 cgiCopyTemplateLang(is_class ? "class-modified.tmpl" :
2837 "printer-modified.tmpl");
ef416fc2 2838 }
2839
2840 cgiEndHTML();
2841}
2842
2843
2844/*
2845 * 'match_string()' - Return the number of matching characters.
2846 */
2847
2848static int /* O - Number of matching characters */
2849match_string(const char *a, /* I - First string */
2850 const char *b) /* I - Second string */
2851{
2852 int count; /* Number of matching characters */
2853
2854
2855 /*
2856 * Loop through both strings until we hit the end of either or we find
2857 * a non-matching character. For the purposes of comparison, we ignore
2858 * whitespace and do a case-insensitive comparison so that we have a
2859 * better chance of finding a match...
2860 */
2861
2862 for (count = 0; *a && *b; a++, b++, count ++)
2863 {
2864 /*
2865 * Skip leading whitespace characters...
2866 */
2867
2868 while (isspace(*a & 255))
2869 a ++;
2870
2871 while (isspace(*b & 255))
2872 b ++;
2873
2874 /*
2875 * Break out if we run out of characters...
2876 */
2877
2878 if (!*a || !*b)
2879 break;
2880
2881 /*
2882 * Do a case-insensitive comparison of the next two chars...
2883 */
2884
2885 if (tolower(*a & 255) != tolower(*b & 255))
2886 break;
2887 }
2888
2889 return (count);
2890}
2891
2892
2893/*
c07d5b2d 2894 * End of "$Id: admin.c 181 2006-06-22 20:01:18Z jlovell $".
ef416fc2 2895 */