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