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