]> git.ipfire.org Git - thirdparty/cups.git/blob - cgi-bin/printers.c
Full sweep of all Clang warnings, plus some bug fixes for incorrect memcpy usage.
[thirdparty/cups.git] / cgi-bin / printers.c
1 /*
2 * "$Id$"
3 *
4 * Printer status CGI for CUPS.
5 *
6 * Copyright 2007-2014 by Apple Inc.
7 * Copyright 1997-2006 by Easy Software Products.
8 *
9 * These coded instructions, statements, and computer programs are the
10 * property of Apple Inc. and are protected by Federal copyright
11 * law. Distribution and use rights are outlined in the file "LICENSE.txt"
12 * which should have been included with this file. If this file is
13 * file is missing or damaged, see the license at "http://www.cups.org/".
14 */
15
16 /*
17 * Include necessary headers...
18 */
19
20 #include "cgi-private.h"
21 #include <errno.h>
22
23
24 /*
25 * Local functions...
26 */
27
28 static void do_printer_op(http_t *http, const char *printer, ipp_op_t op,
29 const char *title);
30 static void show_all_printers(http_t *http, const char *username);
31 static void show_printer(http_t *http, const char *printer);
32
33
34 /*
35 * 'main()' - Main entry for CGI.
36 */
37
38 int /* O - Exit status */
39 main(void)
40 {
41 const char *printer; /* Printer name */
42 const char *user; /* Username */
43 http_t *http; /* Connection to the server */
44 ipp_t *request, /* IPP request */
45 *response; /* IPP response */
46 ipp_attribute_t *attr; /* IPP attribute */
47 const char *op; /* Operation to perform, if any */
48 static const char *def_attrs[] = /* Attributes for default printer */
49 {
50 "printer-name",
51 "printer-uri-supported"
52 };
53
54
55 /*
56 * Get any form variables...
57 */
58
59 cgiInitialize();
60
61 op = cgiGetVariable("OP");
62
63 /*
64 * Set the web interface section...
65 */
66
67 cgiSetVariable("SECTION", "printers");
68 cgiSetVariable("REFRESH_PAGE", "");
69
70 /*
71 * See if we are displaying a printer or all printers...
72 */
73
74 if ((printer = getenv("PATH_INFO")) != NULL)
75 {
76 printer ++;
77
78 if (!*printer)
79 printer = NULL;
80
81 if (printer)
82 cgiSetVariable("PRINTER_NAME", printer);
83 }
84
85 /*
86 * See who is logged in...
87 */
88
89 user = getenv("REMOTE_USER");
90
91 /*
92 * Connect to the HTTP server...
93 */
94
95 http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption());
96
97 /*
98 * Get the default printer...
99 */
100
101 if (!op || !cgiIsPOST())
102 {
103 /*
104 * Get the default destination...
105 */
106
107 request = ippNewRequest(CUPS_GET_DEFAULT);
108
109 ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
110 "requested-attributes",
111 sizeof(def_attrs) / sizeof(def_attrs[0]), NULL, def_attrs);
112
113 if ((response = cupsDoRequest(http, request, "/")) != NULL)
114 {
115 if ((attr = ippFindAttribute(response, "printer-name", IPP_TAG_NAME)) != NULL)
116 cgiSetVariable("DEFAULT_NAME", attr->values[0].string.text);
117
118 if ((attr = ippFindAttribute(response, "printer-uri-supported", IPP_TAG_URI)) != NULL)
119 {
120 char url[HTTP_MAX_URI]; /* New URL */
121
122
123 cgiSetVariable("DEFAULT_URI",
124 cgiRewriteURL(attr->values[0].string.text,
125 url, sizeof(url), NULL));
126 }
127
128 ippDelete(response);
129 }
130
131 /*
132 * See if we need to show a list of printers or the status of a
133 * single printer...
134 */
135
136 if (!printer)
137 show_all_printers(http, user);
138 else
139 show_printer(http, printer);
140 }
141 else if (printer)
142 {
143 if (!*op)
144 {
145 const char *server_port = getenv("SERVER_PORT");
146 /* Port number string */
147 int port = atoi(server_port ? server_port : "0");
148 /* Port number */
149 char uri[1024]; /* URL */
150
151 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri),
152 getenv("HTTPS") ? "https" : "http", NULL,
153 getenv("SERVER_NAME"), port, "/printers/%s", printer);
154
155 printf("Location: %s\n\n", uri);
156 }
157 else if (!strcmp(op, "start-printer"))
158 do_printer_op(http, printer, IPP_RESUME_PRINTER,
159 cgiText(_("Resume Printer")));
160 else if (!strcmp(op, "stop-printer"))
161 do_printer_op(http, printer, IPP_PAUSE_PRINTER,
162 cgiText(_("Pause Printer")));
163 else if (!strcmp(op, "accept-jobs"))
164 do_printer_op(http, printer, CUPS_ACCEPT_JOBS, cgiText(_("Accept Jobs")));
165 else if (!strcmp(op, "reject-jobs"))
166 do_printer_op(http, printer, CUPS_REJECT_JOBS, cgiText(_("Reject Jobs")));
167 else if (!strcmp(op, "purge-jobs"))
168 do_printer_op(http, printer, IPP_PURGE_JOBS, cgiText(_("Purge Jobs")));
169 else if (!_cups_strcasecmp(op, "print-self-test-page"))
170 cgiPrintCommand(http, printer, "PrintSelfTestPage",
171 cgiText(_("Print Self-Test Page")));
172 else if (!_cups_strcasecmp(op, "clean-print-heads"))
173 cgiPrintCommand(http, printer, "Clean all",
174 cgiText(_("Clean Print Heads")));
175 else if (!_cups_strcasecmp(op, "print-test-page"))
176 cgiPrintTestPage(http, printer);
177 else if (!_cups_strcasecmp(op, "move-jobs"))
178 cgiMoveJobs(http, printer, 0);
179 else
180 {
181 /*
182 * Unknown/bad operation...
183 */
184
185 cgiStartHTML(printer);
186 cgiCopyTemplateLang("error-op.tmpl");
187 cgiEndHTML();
188 }
189 }
190 else
191 {
192 /*
193 * Unknown/bad operation...
194 */
195
196 cgiStartHTML(cgiText(_("Printers")));
197 cgiCopyTemplateLang("error-op.tmpl");
198 cgiEndHTML();
199 }
200
201 /*
202 * Close the HTTP server connection...
203 */
204
205 httpClose(http);
206
207 /*
208 * Return with no errors...
209 */
210
211 return (0);
212 }
213
214
215 /*
216 * 'do_printer_op()' - Do a printer operation.
217 */
218
219 static void
220 do_printer_op(http_t *http, /* I - HTTP connection */
221 const char *printer, /* I - Printer name */
222 ipp_op_t op, /* I - Operation to perform */
223 const char *title) /* I - Title of page */
224 {
225 ipp_t *request; /* IPP request */
226 char uri[HTTP_MAX_URI], /* Printer URI */
227 resource[HTTP_MAX_URI]; /* Path for request */
228
229
230 /*
231 * Build a printer request, which requires the following
232 * attributes:
233 *
234 * attributes-charset
235 * attributes-natural-language
236 * printer-uri
237 */
238
239 request = ippNewRequest(op);
240
241 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
242 "localhost", 0, "/printers/%s", printer);
243 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
244 NULL, uri);
245
246 /*
247 * Do the request and get back a response...
248 */
249
250 snprintf(resource, sizeof(resource), "/printers/%s", printer);
251 ippDelete(cupsDoRequest(http, request, resource));
252
253 if (cupsLastError() == IPP_NOT_AUTHORIZED)
254 {
255 puts("Status: 401\n");
256 exit(0);
257 }
258 else if (cupsLastError() > IPP_OK_CONFLICT)
259 {
260 cgiStartHTML(title);
261 cgiShowIPPError(_("Unable to do maintenance command"));
262 }
263 else
264 {
265 /*
266 * Redirect successful updates back to the printer page...
267 */
268
269 char url[1024], /* Printer/class URL */
270 refresh[1024]; /* Refresh URL */
271
272
273 cgiRewriteURL(uri, url, sizeof(url), NULL);
274 cgiFormEncode(uri, url, sizeof(uri));
275 snprintf(refresh, sizeof(refresh), "5;URL=%s", uri);
276 cgiSetVariable("refresh_page", refresh);
277
278 cgiStartHTML(title);
279
280 if (op == IPP_PAUSE_PRINTER)
281 cgiCopyTemplateLang("printer-stop.tmpl");
282 else if (op == IPP_RESUME_PRINTER)
283 cgiCopyTemplateLang("printer-start.tmpl");
284 else if (op == CUPS_ACCEPT_JOBS)
285 cgiCopyTemplateLang("printer-accept.tmpl");
286 else if (op == CUPS_REJECT_JOBS)
287 cgiCopyTemplateLang("printer-reject.tmpl");
288 else if (op == IPP_PURGE_JOBS)
289 cgiCopyTemplateLang("printer-purge.tmpl");
290 }
291
292 cgiEndHTML();
293 }
294
295
296 /*
297 * 'show_all_printers()' - Show all printers...
298 */
299
300 static void
301 show_all_printers(http_t *http, /* I - Connection to server */
302 const char *user) /* I - Username */
303 {
304 int i; /* Looping var */
305 ipp_t *request, /* IPP request */
306 *response; /* IPP response */
307 cups_array_t *printers; /* Array of printer objects */
308 ipp_attribute_t *printer; /* Printer object */
309 int ascending, /* Order of printers (0 = descending) */
310 first, /* First printer to show */
311 count; /* Number of printers */
312 const char *var; /* Form variable */
313 void *search; /* Search data */
314 char val[1024]; /* Form variable */
315
316
317 fprintf(stderr, "DEBUG: show_all_printers(http=%p, user=\"%s\")\n",
318 http, user ? user : "(null)");
319
320 /*
321 * Show the standard header...
322 */
323
324 cgiStartHTML(cgiText(_("Printers")));
325
326 /*
327 * Build a CUPS_GET_PRINTERS request, which requires the following
328 * attributes:
329 *
330 * attributes-charset
331 * attributes-natural-language
332 * printer-type
333 * printer-type-mask
334 * requesting-user-name
335 */
336
337 request = ippNewRequest(CUPS_GET_PRINTERS);
338
339 ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_ENUM,
340 "printer-type", 0);
341 ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_ENUM,
342 "printer-type-mask", CUPS_PRINTER_CLASS);
343
344 if (user)
345 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
346 "requesting-user-name", NULL, user);
347
348 cgiGetAttributes(request, "printers.tmpl");
349
350 /*
351 * Do the request and get back a response...
352 */
353
354 if ((response = cupsDoRequest(http, request, "/")) != NULL)
355 {
356 /*
357 * Get a list of matching job objects.
358 */
359
360 if ((var = cgiGetVariable("QUERY")) != NULL &&
361 !cgiGetVariable("CLEAR"))
362 search = cgiCompileSearch(var);
363 else
364 search = NULL;
365
366 printers = cgiGetIPPObjects(response, search);
367 count = cupsArrayCount(printers);
368
369 if (search)
370 cgiFreeSearch(search);
371
372 /*
373 * Figure out which printers to display...
374 */
375
376 if ((var = cgiGetVariable("FIRST")) != NULL)
377 first = atoi(var);
378 else
379 first = 0;
380
381 if (first >= count)
382 first = count - CUPS_PAGE_MAX;
383
384 first = (first / CUPS_PAGE_MAX) * CUPS_PAGE_MAX;
385
386 if (first < 0)
387 first = 0;
388
389 sprintf(val, "%d", count);
390 cgiSetVariable("TOTAL", val);
391
392 if ((var = cgiGetVariable("ORDER")) != NULL && *var)
393 ascending = !_cups_strcasecmp(var, "asc");
394 else
395 ascending = 1;
396
397 if (ascending)
398 {
399 for (i = 0, printer = (ipp_attribute_t *)cupsArrayIndex(printers, first);
400 i < CUPS_PAGE_MAX && printer;
401 i ++, printer = (ipp_attribute_t *)cupsArrayNext(printers))
402 cgiSetIPPObjectVars(printer, NULL, i);
403 }
404 else
405 {
406 for (i = 0, printer = (ipp_attribute_t *)cupsArrayIndex(printers, count - first - 1);
407 i < CUPS_PAGE_MAX && printer;
408 i ++, printer = (ipp_attribute_t *)cupsArrayPrev(printers))
409 cgiSetIPPObjectVars(printer, NULL, i);
410 }
411
412 /*
413 * Save navigation URLs...
414 */
415
416 cgiSetVariable("THISURL", "/printers/");
417
418 if (first > 0)
419 {
420 sprintf(val, "%d", first - CUPS_PAGE_MAX);
421 cgiSetVariable("PREV", val);
422 }
423
424 if ((first + CUPS_PAGE_MAX) < count)
425 {
426 sprintf(val, "%d", first + CUPS_PAGE_MAX);
427 cgiSetVariable("NEXT", val);
428 }
429
430 /*
431 * Then show everything...
432 */
433
434 cgiCopyTemplateLang("search.tmpl");
435
436 cgiCopyTemplateLang("printers-header.tmpl");
437
438 if (count > CUPS_PAGE_MAX)
439 cgiCopyTemplateLang("pager.tmpl");
440
441 cgiCopyTemplateLang("printers.tmpl");
442
443 if (count > CUPS_PAGE_MAX)
444 cgiCopyTemplateLang("pager.tmpl");
445
446 /*
447 * Delete the response...
448 */
449
450 cupsArrayDelete(printers);
451 ippDelete(response);
452 }
453 else
454 {
455 /*
456 * Show the error...
457 */
458
459 cgiShowIPPError(_("Unable to get printer list"));
460 }
461
462 cgiEndHTML();
463 }
464
465
466 /*
467 * 'show_printer()' - Show a single printer.
468 */
469
470 static void
471 show_printer(http_t *http, /* I - Connection to server */
472 const char *printer) /* I - Name of printer */
473 {
474 ipp_t *request, /* IPP request */
475 *response; /* IPP response */
476 ipp_attribute_t *attr; /* IPP attribute */
477 char uri[HTTP_MAX_URI]; /* Printer URI */
478 char refresh[1024]; /* Refresh URL */
479
480
481 fprintf(stderr, "DEBUG: show_printer(http=%p, printer=\"%s\")\n",
482 http, printer ? printer : "(null)");
483
484 /*
485 * Build an IPP_GET_PRINTER_ATTRIBUTES request, which requires the following
486 * attributes:
487 *
488 * attributes-charset
489 * attributes-natural-language
490 * printer-uri
491 */
492
493 request = ippNewRequest(IPP_GET_PRINTER_ATTRIBUTES);
494
495 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
496 "localhost", 0, "/printers/%s", printer);
497 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL,
498 uri);
499
500 cgiGetAttributes(request, "printer.tmpl");
501
502 /*
503 * Do the request and get back a response...
504 */
505
506 if ((response = cupsDoRequest(http, request, "/")) != NULL)
507 {
508 /*
509 * Got the result; set the CGI variables and check the status of a
510 * single-queue request...
511 */
512
513 cgiSetIPPVars(response, NULL, NULL, NULL, 0);
514
515 if (printer && (attr = ippFindAttribute(response, "printer-state",
516 IPP_TAG_ENUM)) != NULL &&
517 attr->values[0].integer == IPP_PRINTER_PROCESSING)
518 {
519 /*
520 * Printer is processing - automatically refresh the page until we
521 * are done printing...
522 */
523
524 cgiFormEncode(uri, printer, sizeof(uri));
525 snprintf(refresh, sizeof(refresh), "10;URL=/printers/%s", uri);
526 cgiSetVariable("refresh_page", refresh);
527 }
528
529 /*
530 * Delete the response...
531 */
532
533 ippDelete(response);
534
535 /*
536 * Show the standard header...
537 */
538
539 cgiStartHTML(printer);
540
541 /*
542 * Show the printer status...
543 */
544
545 cgiCopyTemplateLang("printer.tmpl");
546
547 /*
548 * Show jobs for the specified printer...
549 */
550
551 cgiCopyTemplateLang("printer-jobs-header.tmpl");
552 cgiShowJobs(http, printer);
553 }
554 else
555 {
556 /*
557 * Show the IPP error...
558 */
559
560 cgiStartHTML(printer);
561 cgiShowIPPError(_("Unable to get printer status"));
562 }
563
564 cgiEndHTML();
565 }
566
567
568 /*
569 * End of "$Id$".
570 */