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