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