]> git.ipfire.org Git - thirdparty/cups.git/blob - cgi-bin/classes.c
2685e66a3e14762fcd7a25579a2b6eb52d0f3d13
[thirdparty/cups.git] / cgi-bin / classes.c
1 /*
2 * "$Id$"
3 *
4 * Class 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
22
23 /*
24 * Local functions...
25 */
26
27 static void do_class_op(http_t *http, const char *printer, ipp_op_t op,
28 const char *title);
29 static void show_all_classes(http_t *http, const char *username);
30 static void show_class(http_t *http, const char *printer);
31
32
33 /*
34 * 'main()' - Main entry for CGI.
35 */
36
37 int /* O - Exit status */
38 main(void)
39 {
40 const char *pclass; /* Class name */
41 const char *user; /* Username */
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 */
46 const char *op; /* Operation to perform, if any */
47 static const char *def_attrs[] = /* Attributes for default printer */
48 {
49 "printer-name",
50 "printer-uri-supported"
51 };
52
53
54 /*
55 * Get any form variables...
56 */
57
58 cgiInitialize();
59
60 op = cgiGetVariable("OP");
61
62 /*
63 * Set the web interface section...
64 */
65
66 cgiSetVariable("SECTION", "classes");
67 cgiSetVariable("REFRESH_PAGE", "");
68
69 /*
70 * See if we are displaying a printer or all classes...
71 */
72
73 if ((pclass = getenv("PATH_INFO")) != NULL)
74 {
75 pclass ++;
76
77 if (!*pclass)
78 pclass = NULL;
79
80 if (pclass)
81 cgiSetVariable("PRINTER_NAME", pclass);
82 }
83
84 /*
85 * See who is logged in...
86 */
87
88 user = getenv("REMOTE_USER");
89
90 /*
91 * Connect to the HTTP server...
92 */
93
94 http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption());
95
96 /*
97 * Get the default printer...
98 */
99
100 if (!op || !cgiIsPOST())
101 {
102 /*
103 * Get the default destination...
104 */
105
106 request = ippNewRequest(CUPS_GET_DEFAULT);
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 /*
131 * See if we need to show a list of classes or the status of a
132 * single printer...
133 */
134
135 if (!pclass)
136 show_all_classes(http, user);
137 else
138 show_class(http, pclass);
139 }
140 else if (pclass)
141 {
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"))
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, "cancel-jobs"))
165 do_class_op(http, pclass, IPP_OP_CANCEL_JOBS, cgiText(_("Cancel Jobs")));
166 else if (!_cups_strcasecmp(op, "print-test-page"))
167 cgiPrintTestPage(http, pclass);
168 else if (!_cups_strcasecmp(op, "move-jobs"))
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 }
181 else
182 {
183 /*
184 * Unknown/bad operation...
185 */
186
187 cgiStartHTML(cgiText(_("Classes")));
188 cgiCopyTemplateLang("error-op.tmpl");
189 cgiEndHTML();
190 }
191
192 /*
193 * Close the HTTP server connection...
194 */
195
196 httpClose(http);
197
198 /*
199 * Return with no errors...
200 */
201
202 return (0);
203 }
204
205
206 /*
207 * 'do_class_op()' - Do a class operation.
208 */
209
210 static void
211 do_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);
252 cgiShowIPPError(_("Unable to do maintenance command"));
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_OP_CANCEL_JOBS)
282 cgiCopyTemplateLang("printer-cancel-jobs.tmpl");
283 }
284
285 cgiEndHTML();
286 }
287
288
289 /*
290 * 'show_all_classes()' - Show all classes...
291 */
292
293 static void
294 show_all_classes(http_t *http, /* I - Connection to server */
295 const char *user) /* I - Username */
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 */
307 char val[1024]; /* Form variable */
308
309
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
327 if (user)
328 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
329 "requesting-user-name", NULL, user);
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 {
339 /*
340 * Get a list of matching job objects.
341 */
342
343 if ((var = cgiGetVariable("QUERY")) != NULL &&
344 !cgiGetVariable("CLEAR"))
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);
354
355 /*
356 * Figure out which classes to display...
357 */
358
359 if ((var = cgiGetVariable("FIRST")) != NULL)
360 first = atoi(var);
361 else
362 first = 0;
363
364 if (first >= count)
365 first = count - CUPS_PAGE_MAX;
366
367 first = (first / CUPS_PAGE_MAX) * CUPS_PAGE_MAX;
368
369 if (first < 0)
370 first = 0;
371
372 sprintf(val, "%d", count);
373 cgiSetVariable("TOTAL", val);
374
375 if ((var = cgiGetVariable("ORDER")) != NULL && *var)
376 ascending = !_cups_strcasecmp(var, "asc");
377 else
378 ascending = 1;
379
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 }
394
395 /*
396 * Save navigation URLs...
397 */
398
399 cgiSetVariable("THISURL", "/classes/");
400
401 if (first > 0)
402 {
403 sprintf(val, "%d", first - CUPS_PAGE_MAX);
404 cgiSetVariable("PREV", val);
405 }
406
407 if ((first + CUPS_PAGE_MAX) < count)
408 {
409 sprintf(val, "%d", first + CUPS_PAGE_MAX);
410 cgiSetVariable("NEXT", val);
411 }
412
413 /*
414 * Then show everything...
415 */
416
417 cgiCopyTemplateLang("search.tmpl");
418
419 cgiCopyTemplateLang("classes-header.tmpl");
420
421 if (count > CUPS_PAGE_MAX)
422 cgiCopyTemplateLang("pager.tmpl");
423
424 cgiCopyTemplateLang("classes.tmpl");
425
426 if (count > CUPS_PAGE_MAX)
427 cgiCopyTemplateLang("pager.tmpl");
428
429 /*
430 * Delete the response...
431 */
432
433 cupsArrayDelete(classes);
434 ippDelete(response);
435 }
436 else
437 {
438 /*
439 * Show the error...
440 */
441
442 cgiShowIPPError(_("Unable to get class list"));
443 }
444
445 cgiEndHTML();
446 }
447
448
449 /*
450 * 'show_class()' - Show a single class.
451 */
452
453 static void
454 show_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 */
472
473 request = ippNewRequest(IPP_GET_PRINTER_ATTRIBUTES);
474
475 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
476 "localhost", 0, "/classes/%s", pclass);
477 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL,
478 uri);
479
480 cgiGetAttributes(request, "class.tmpl");
481
482 /*
483 * Do the request and get back a response...
484 */
485
486 if ((response = cupsDoRequest(http, request, "/")) != NULL)
487 {
488 /*
489 * Got the result; set the CGI variables and check the status of a
490 * single-queue request...
491 */
492
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)
498 {
499 /*
500 * Class is processing - automatically refresh the page until we
501 * are done printing...
502 */
503
504 cgiFormEncode(uri, pclass, sizeof(uri));
505 snprintf(refresh, sizeof(refresh), "10;URL=/classes/%s", uri);
506 cgiSetVariable("refresh_page", refresh);
507 }
508
509 /*
510 * Delete the response...
511 */
512
513 ippDelete(response);
514
515 /*
516 * Show the standard header...
517 */
518
519 cgiStartHTML(pclass);
520
521 /*
522 * Show the class status...
523 */
524
525 cgiCopyTemplateLang("class.tmpl");
526
527 /*
528 * Show jobs for the specified class...
529 */
530
531 cgiCopyTemplateLang("class-jobs-header.tmpl");
532 cgiShowJobs(http, pclass);
533 }
534 else
535 {
536 /*
537 * Show the IPP error...
538 */
539
540 cgiStartHTML(pclass);
541 cgiShowIPPError(_("Unable to get class status"));
542 }
543
544 cgiEndHTML();
545 }
546
547
548 /*
549 * End of "$Id$".
550 */