]> git.ipfire.org Git - thirdparty/cups.git/blame - cgi-bin/ipp-var.c
Import CUPS 1.4svn r7023 into easysw/current.
[thirdparty/cups.git] / cgi-bin / ipp-var.c
CommitLineData
ef416fc2 1/*
2e4ff8af 2 * "$Id: ipp-var.c 6889 2007-08-29 22:23:35Z mike $"
ef416fc2 3 *
4 * CGI <-> IPP variable routines for the Common UNIX Printing System (CUPS).
5 *
bc44d920 6 * Copyright 2007 by Apple Inc.
f7deaa1a 7 * Copyright 1997-2007 by Easy Software Products.
ef416fc2 8 *
9 * These coded instructions, statements, and computer programs are the
bc44d920 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 * Contents:
16 *
17 * cgiGetAttributes() - Get the list of attributes that are needed
18 * by the template file.
fa73b229 19 * cgiGetIPPObjects() - Get the objects in an IPP response.
20 * cgiMoveJobs() - Move one or more jobs.
21 * cgiPrintTestPage() - Print a test page.
ef416fc2 22 * cgiRewriteURL() - Rewrite a printer URI into a web browser URL...
23 * cgiSetIPPObjectVars() - Set CGI variables from an IPP object.
24 * cgiSetIPPVars() - Set CGI variables from an IPP response.
fa73b229 25 * cgiShowIPPError() - Show the last IPP error message.
26 * cgiShowJobs() - Show print jobs.
27 * cgiText() - Return localized text.
ef416fc2 28 */
29
30/*
31 * Include necessary headers...
32 */
33
34#include "cgi-private.h"
35
36
37/*
38 * 'cgiGetAttributes()' - Get the list of attributes that are needed
39 * by the template file.
40 */
41
42void
43cgiGetAttributes(ipp_t *request, /* I - IPP request */
44 const char *tmpl) /* I - Base filename */
45{
46 int num_attrs; /* Number of attributes */
47 char *attrs[1000]; /* Attributes */
48 int i; /* Looping var */
49 char filename[1024], /* Filename */
50 locale[16]; /* Locale name */
51 const char *directory, /* Directory */
52 *lang; /* Language */
53 FILE *in; /* Input file */
54 int ch; /* Character from file */
55 char name[255], /* Name of variable */
56 *nameptr; /* Pointer into name */
57
58
59 /*
60 * Convert the language to a locale name...
61 */
62
63 if ((lang = getenv("LANG")) != NULL)
64 {
65 for (i = 0; lang[i] && i < 15; i ++)
66 if (isalnum(lang[i] & 255))
67 locale[i] = tolower(lang[i]);
68 else
69 locale[i] = '_';
70
71 locale[i] = '\0';
72 }
73 else
74 locale[0] = '\0';
75
76 /*
77 * See if we have a template file for this language...
78 */
79
80 directory = cgiGetTemplateDir();
81
82 snprintf(filename, sizeof(filename), "%s/%s/%s", directory, locale, tmpl);
83 if (access(filename, 0))
84 {
85 locale[2] = '\0';
86
87 snprintf(filename, sizeof(filename), "%s/%s/%s", directory, locale, tmpl);
88 if (access(filename, 0))
89 snprintf(filename, sizeof(filename), "%s/%s", directory, tmpl);
90 }
91
92 /*
93 * Open the template file...
94 */
95
96 if ((in = fopen(filename, "r")) == NULL)
97 return;
98
99 /*
100 * Loop through the file adding attribute names as needed...
101 */
102
103 num_attrs = 0;
d09495fa 104 attrs[0] = NULL; /* Eliminate compiler warning */
ef416fc2 105
106 while ((ch = getc(in)) != EOF)
107 if (ch == '\\')
108 getc(in);
109 else if (ch == '{' && num_attrs < (sizeof(attrs) / sizeof(attrs[0])))
110 {
111 /*
112 * Grab the name...
113 */
114
115 for (nameptr = name; (ch = getc(in)) != EOF;)
116 if (strchr("}]<>=! \t\n", ch))
117 break;
118 else if (nameptr > name && ch == '?')
119 break;
120 else if (nameptr < (name + sizeof(name) - 1))
121 {
122 if (ch == '_')
123 *nameptr++ = '-';
124 else
125 *nameptr++ = ch;
126 }
127
128 *nameptr = '\0';
129
130 if (!strncmp(name, "printer_state_history", 21))
131 strcpy(name, "printer_state_history");
132
133 /*
134 * Possibly add it to the list of attributes...
135 */
136
137 for (i = 0; i < num_attrs; i ++)
138 if (!strcmp(attrs[i], name))
139 break;
140
141 if (i >= num_attrs)
142 {
143 attrs[num_attrs] = strdup(name);
144 num_attrs ++;
145 }
146 }
147
148 /*
149 * If we have attributes, add a requested-attributes attribute to the
150 * request...
151 */
152
153 if (num_attrs > 0)
154 {
155 ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
156 "requested-attributes", num_attrs, NULL, (const char **)attrs);
157
158 for (i = 0; i < num_attrs; i ++)
159 free(attrs[i]);
160 }
161}
162
163
164/*
fa73b229 165 * 'cgiGetIPPObjects()' - Get the objects in an IPP response.
ef416fc2 166 */
167
168cups_array_t * /* O - Array of objects */
169cgiGetIPPObjects(ipp_t *response, /* I - IPP response */
170 void *search) /* I - Search filter */
171{
172 int i; /* Looping var */
173 cups_array_t *objs; /* Array of objects */
174 ipp_attribute_t *attr, /* Current attribute */
175 *first; /* First attribute for object */
176 ipp_tag_t group; /* Current group tag */
177 int add; /* Add this object to the array? */
178
179
180 if (!response)
181 return (0);
182
183 for (add = 0, first = NULL, objs = cupsArrayNew(NULL, NULL),
184 group = IPP_TAG_ZERO, attr = response->attrs;
185 attr;
186 attr = attr->next)
187 {
188 if (attr->group_tag != group)
189 {
190 group = attr->group_tag;
191
192 if (group != IPP_TAG_ZERO && group != IPP_TAG_OPERATION)
193 {
194 first = attr;
195 add = 0;
196 }
197 else if (add && first)
198 {
199 cupsArrayAdd(objs, first);
200
201 add = 0;
202 first = NULL;
203 }
204 }
205
206 if (attr->name && attr->group_tag != IPP_TAG_OPERATION && !add)
207 {
208 if (!search)
209 {
210 /*
211 * Add all objects if there is no search...
212 */
213
214 add = 1;
215 }
216 else
217 {
218 /*
219 * Check the search string against the string and integer values.
220 */
221
222 switch (attr->value_tag)
223 {
224 case IPP_TAG_TEXTLANG :
225 case IPP_TAG_NAMELANG :
226 case IPP_TAG_TEXT :
227 case IPP_TAG_NAME :
228 case IPP_TAG_KEYWORD :
229 case IPP_TAG_URI :
230 case IPP_TAG_MIMETYPE :
231 for (i = 0; !add && i < attr->num_values; i ++)
232 if (cgiDoSearch(search, attr->values[i].string.text))
233 add = 1;
234 break;
235
236 case IPP_TAG_INTEGER :
237 for (i = 0; !add && i < attr->num_values; i ++)
238 {
239 char buf[255]; /* Number buffer */
240
241
242 sprintf(buf, "%d", attr->values[i].integer);
243
244 if (cgiDoSearch(search, buf))
245 add = 1;
246 }
247 break;
248
249 default :
250 break;
251 }
252 }
253 }
254 }
255
256 if (add && first)
257 cupsArrayAdd(objs, first);
258
259 return (objs);
260}
261
262
fa73b229 263/*
264 * 'cgiMoveJobs()' - Move one or more jobs.
265 *
266 * At least one of dest or job_id must be non-zero/NULL.
267 */
268
269void
270cgiMoveJobs(http_t *http, /* I - Connection to server */
271 const char *dest, /* I - Destination or NULL */
272 int job_id) /* I - Job ID or 0 for all */
273{
274 int i; /* Looping var */
275 const char *user; /* Username */
276 ipp_t *request, /* IPP request */
277 *response; /* IPP response */
278 ipp_attribute_t *attr; /* Current attribute */
279 const char *name; /* Destination name */
280 const char *job_printer_uri; /* JOB_PRINTER_URI form variable */
281 char current_dest[1024]; /* Current destination */
282
283
284 /*
285 * See who is logged in...
286 */
287
288 if ((user = getenv("REMOTE_USER")) == NULL)
289 user = "guest";
290
291 /*
292 * See if the user has already selected a new destination...
293 */
294
295 if ((job_printer_uri = cgiGetVariable("JOB_PRINTER_URI")) == NULL)
296 {
297 /*
298 * Make sure necessary form variables are set...
299 */
300
301 if (job_id)
302 {
303 char temp[255]; /* Temporary string */
304
305
306 sprintf(temp, "%d", job_id);
307 cgiSetVariable("JOB_ID", temp);
308 }
309
310 if (dest)
311 cgiSetVariable("PRINTER_NAME", dest);
312
313 /*
314 * No new destination specified, show the user what the available
315 * printers/classes are...
316 */
317
318 if (!dest)
319 {
320 /*
321 * Get the current destination for job N...
322 */
323
324 char job_uri[1024]; /* Job URI */
325
326
327 request = ippNewRequest(IPP_GET_JOB_ATTRIBUTES);
328
329 snprintf(job_uri, sizeof(job_uri), "ipp://localhost/jobs/%d", job_id);
330 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri",
331 NULL, job_uri);
332 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
333 "requested-attributes", NULL, "job-printer-uri");
334
335 if ((response = cupsDoRequest(http, request, "/")) != NULL)
336 {
337 if ((attr = ippFindAttribute(response, "job-printer-uri",
338 IPP_TAG_URI)) != NULL)
339 {
340 /*
341 * Pull the name from the URI...
342 */
343
344 strlcpy(current_dest, strrchr(attr->values[0].string.text, '/') + 1,
345 sizeof(current_dest));
346 dest = current_dest;
347 }
348
349 ippDelete(response);
350 }
351
352 if (!dest)
353 {
354 /*
355 * Couldn't get the current destination...
356 */
357
358 cgiStartHTML(cgiText(_("Move Job")));
359 cgiShowIPPError(_("Unable to find destination for job!"));
360 cgiEndHTML();
361 return;
362 }
363 }
364
365 /*
366 * Get the list of available destinations...
367 */
368
369 request = ippNewRequest(CUPS_GET_PRINTERS);
370
371 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
372 "requested-attributes", NULL, "printer-uri-supported");
373
374 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
375 "requesting-user-name", NULL, user);
376
377 if ((response = cupsDoRequest(http, request, "/")) != NULL)
378 {
379 for (i = 0, attr = ippFindAttribute(response, "printer-uri-supported",
380 IPP_TAG_URI);
381 attr;
382 attr = ippFindNextAttribute(response, "printer-uri-supported",
383 IPP_TAG_URI))
384 {
385 /*
386 * Pull the name from the URI...
387 */
388
389 name = strrchr(attr->values[0].string.text, '/') + 1;
390
391 /*
392 * If the name is not the same as the current destination, add it!
393 */
394
395 if (strcasecmp(name, dest))
396 {
397 cgiSetArray("JOB_PRINTER_URI", i, attr->values[0].string.text);
398 cgiSetArray("JOB_PRINTER_NAME", i, name);
399 i ++;
400 }
401 }
402
403 ippDelete(response);
404 }
405
406 /*
407 * Show the form...
408 */
409
410 if (job_id)
411 cgiStartHTML(cgiText(_("Move Job")));
412 else
413 cgiStartHTML(cgiText(_("Move All Jobs")));
414
415 cgiCopyTemplateLang("job-move.tmpl");
416 }
417 else
418 {
419 /*
420 * Try moving the job or jobs...
421 */
422
423 char uri[1024], /* Job/printer URI */
424 resource[1024], /* Post resource */
425 refresh[1024]; /* Refresh URL */
426 const char *job_printer_name; /* New printer name */
427
428
429 request = ippNewRequest(CUPS_MOVE_JOB);
430
431 if (job_id)
432 {
433 /*
434 * Move 1 job...
435 */
436
437 snprintf(resource, sizeof(resource), "/jobs/%d", job_id);
438
439 snprintf(uri, sizeof(uri), "ipp://localhost/jobs/%d", job_id);
440 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri",
441 NULL, uri);
442 }
443 else
444 {
445 /*
446 * Move all active jobs on a destination...
447 */
448
449 snprintf(resource, sizeof(resource), "/%s/%s",
450 cgiGetVariable("SECTION"), dest);
451
a4d04587 452 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
453 "localhost", ippPort(), "/%s/%s",
454 cgiGetVariable("SECTION"), dest);
fa73b229 455 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
456 NULL, uri);
457 }
458
459 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-printer-uri",
460 NULL, job_printer_uri);
461
462 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
463 "requesting-user-name", NULL, user);
464
465 ippDelete(cupsDoRequest(http, request, resource));
466
467 /*
468 * Show the results...
469 */
470
471 job_printer_name = strrchr(job_printer_uri, '/') + 1;
472
473 if (cupsLastError() <= IPP_OK_CONFLICT)
474 {
475 cgiRewriteURL(job_printer_uri, resource, sizeof(resource), NULL);
476 cgiFormEncode(uri, resource, sizeof(uri));
f301802f 477 snprintf(refresh, sizeof(refresh), "2;URL=%s", uri);
fa73b229 478 cgiSetVariable("refresh_page", refresh);
479 }
480
481 if (job_id)
482 cgiStartHTML(cgiText(_("Move Job")));
483 else
484 cgiStartHTML(cgiText(_("Move All Jobs")));
485
486 if (cupsLastError() > IPP_OK_CONFLICT)
487 {
488 if (job_id)
489 cgiShowIPPError(_("Unable to move job"));
490 else
491 cgiShowIPPError(_("Unable to move jobs"));
492 }
493 else
494 {
495 cgiSetVariable("JOB_PRINTER_NAME", job_printer_name);
496 cgiCopyTemplateLang("job-moved.tmpl");
497 }
498 }
499
500 cgiEndHTML();
501}
502
503
504/*
505 * 'cgiPrintTestPage()' - Print a test page.
506 */
507
508void
509cgiPrintTestPage(http_t *http, /* I - Connection to server */
510 const char *dest) /* I - Destination printer/class */
511{
512 ipp_t *request, /* IPP request */
513 *response; /* IPP response */
514 char uri[HTTP_MAX_URI], /* Printer URI */
515 resource[1024], /* POST resource path */
516 refresh[1024], /* Refresh URL */
517 filename[1024]; /* Test page filename */
518 const char *datadir; /* CUPS_DATADIR env var */
519 const char *user; /* Username */
520
521
522 /*
523 * See who is logged in...
524 */
525
526 if ((user = getenv("REMOTE_USER")) == NULL)
527 user = "guest";
528
529 /*
530 * Locate the test page file...
531 */
532
533 if ((datadir = getenv("CUPS_DATADIR")) == NULL)
534 datadir = CUPS_DATADIR;
535
536 snprintf(filename, sizeof(filename), "%s/data/testprint.ps", datadir);
537
538 /*
539 * Point to the printer/class...
540 */
541
542 snprintf(resource, sizeof(resource), "/%s/%s", cgiGetVariable("SECTION"),
543 dest);
544
a4d04587 545 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
546 "localhost", ippPort(), "/%s/%s", cgiGetVariable("SECTION"),
547 dest);
fa73b229 548
549 /*
550 * Build an IPP_PRINT_JOB request, which requires the following
551 * attributes:
552 *
553 * attributes-charset
554 * attributes-natural-language
555 * printer-uri
556 * requesting-user-name
557 * document-format
558 */
559
560 request = ippNewRequest(IPP_PRINT_JOB);
561
562 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
563 NULL, uri);
564
565 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
566 "requesting-user-name", NULL, user);
567
568 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "job-name",
569 NULL, "Test Page");
570
571 ippAddString(request, IPP_TAG_JOB, IPP_TAG_MIMETYPE, "document-format",
572 NULL, "application/postscript");
573
574 /*
575 * Do the request and get back a response...
576 */
577
578 if ((response = cupsDoFileRequest(http, request, resource,
579 filename)) != NULL)
580 {
581 cgiSetIPPVars(response, NULL, NULL, NULL, 0);
582
583 ippDelete(response);
584 }
585
586 if (cupsLastError() <= IPP_OK_CONFLICT)
587 {
588 /*
589 * Automatically reload the printer status page...
590 */
591
592 cgiFormEncode(uri, resource, sizeof(uri));
f301802f 593 snprintf(refresh, sizeof(refresh), "2;URL=%s", uri);
fa73b229 594 cgiSetVariable("refresh_page", refresh);
595 }
596
597 cgiStartHTML(cgiText(_("Print Test Page")));
598
599 if (cupsLastError() > IPP_OK_CONFLICT)
600 cgiShowIPPError(_("Unable to print test page:"));
601 else
602 {
603 cgiSetVariable("PRINTER_NAME", dest);
604
605 cgiCopyTemplateLang("test-page.tmpl");
606 }
607
608 cgiEndHTML();
609}
610
611
ef416fc2 612/*
613 * 'cgiRewriteURL()' - Rewrite a printer URI into a web browser URL...
614 */
615
616char * /* O - New URL */
617cgiRewriteURL(const char *uri, /* I - Current URI */
618 char *url, /* O - New URL */
619 int urlsize, /* I - Size of URL buffer */
620 const char *newresource) /* I - Replacement resource */
621{
622 char method[HTTP_MAX_URI],
623 userpass[HTTP_MAX_URI],
624 hostname[HTTP_MAX_URI],
625 rawresource[HTTP_MAX_URI],
626 resource[HTTP_MAX_URI],
627 /* URI components... */
628 *rawptr, /* Pointer into rawresource */
629 *resptr; /* Pointer into resource */
630 int port; /* Port number */
631 static int ishttps = -1; /* Using encryption? */
632 static const char *server; /* Name of server */
633 static char servername[1024];
634 /* Local server name */
635 static const char hexchars[] = "0123456789ABCDEF";
636 /* Hexadecimal conversion characters */
637
638
639 /*
640 * Check if we have been called before...
641 */
642
643 if (ishttps < 0)
644 {
645 /*
646 * No, initialize static vars for the conversion...
647 *
648 * First get the server name associated with the client interface as
649 * well as the locally configured hostname. We'll check *both* of
650 * these to see if the printer URL is local...
651 */
652
653 if ((server = getenv("SERVER_NAME")) == NULL)
654 server = "";
655
757d2cad 656 httpGetHostname(NULL, servername, sizeof(servername));
ef416fc2 657
658 /*
659 * Then flag whether we are using SSL on this connection...
660 */
661
662 ishttps = getenv("HTTPS") != NULL;
663 }
664
665 /*
666 * Convert the URI to a URL...
667 */
668
a4d04587 669 httpSeparateURI(HTTP_URI_CODING_ALL, uri, method, sizeof(method), userpass,
670 sizeof(userpass), hostname, sizeof(hostname), &port,
ef416fc2 671 rawresource, sizeof(rawresource));
672
673 if (!strcmp(method, "ipp") ||
674 !strcmp(method, "http") ||
675 !strcmp(method, "https"))
676 {
677 if (newresource)
678 {
679 /*
680 * Force the specified resource name instead of the one in the URL...
681 */
682
683 strlcpy(resource, newresource, sizeof(resource));
684 }
685 else
686 {
687 /*
688 * Rewrite the resource string so it doesn't contain any
689 * illegal chars...
690 */
691
692 for (rawptr = rawresource, resptr = resource; *rawptr; rawptr ++)
693 if ((*rawptr & 128) || *rawptr == '%' || *rawptr == ' ' ||
694 *rawptr == '#' || *rawptr == '?' ||
695 *rawptr == '.') /* For MSIE */
696 {
697 if (resptr < (resource + sizeof(resource) - 3))
698 {
699 *resptr++ = '%';
700 *resptr++ = hexchars[(*rawptr >> 4) & 15];
701 *resptr++ = hexchars[*rawptr & 15];
702 }
703 }
704 else if (resptr < (resource + sizeof(resource) - 1))
705 *resptr++ = *rawptr;
706
707 *resptr = '\0';
708 }
709
710 /*
711 * Map local access to a local URI...
712 */
713
714 if (!strcasecmp(hostname, "localhost") ||
715 !strncasecmp(hostname, "localhost.", 10) ||
716 !strcasecmp(hostname, server) ||
717 !strcasecmp(hostname, servername))
718 {
719 /*
720 * Make URI relative to the current server...
721 */
722
723 strlcpy(url, resource, urlsize);
724 }
725 else
726 {
727 /*
728 * Rewrite URI with HTTP/HTTPS scheme...
729 */
730
731 if (userpass[0])
732 snprintf(url, urlsize, "%s://%s@%s:%d%s",
733 ishttps ? "https" : "http",
734 userpass, hostname, port, resource);
735 else
736 snprintf(url, urlsize, "%s://%s:%d%s",
737 ishttps ? "https" : "http",
738 hostname, port, resource);
739 }
740 }
741 else
742 strlcpy(url, uri, urlsize);
743
744 return (url);
745}
746
747
748/*
749 * 'cgiSetIPPObjectVars()' - Set CGI variables from an IPP object.
750 */
751
752ipp_attribute_t * /* O - Next object */
753cgiSetIPPObjectVars(
754 ipp_attribute_t *obj, /* I - Response data to be copied... */
755 const char *prefix, /* I - Prefix for name or NULL */
756 int element) /* I - Parent element number */
757{
758 ipp_attribute_t *attr; /* Attribute in response... */
759 int i; /* Looping var */
760 char name[1024], /* Name of attribute */
761 *nameptr, /* Pointer into name */
762 value[16384], /* Value(s) */
763 *valptr; /* Pointer into value */
764 struct tm *date; /* Date information */
765
766
767 fprintf(stderr, "DEBUG2: cgiSetIPPObjectVars(obj=%p, prefix=\"%s\", "
768 "element=%d)\n",
f301802f 769 obj, prefix ? prefix : "(null)", element);
ef416fc2 770
771 /*
772 * Set common CGI template variables...
773 */
774
775 if (!prefix)
776 cgiSetServerVersion();
777
778 /*
779 * Loop through the attributes and set them for the template...
780 */
781
782 for (attr = obj; attr && attr->group_tag != IPP_TAG_ZERO; attr = attr->next)
783 {
784 /*
785 * Copy the attribute name, substituting "_" for "-"...
786 */
787
788 if (!attr->name)
789 continue;
790
791 if (prefix)
792 {
793 snprintf(name, sizeof(name), "%s.", prefix);
794 nameptr = name + strlen(name);
795 }
796 else
797 nameptr = name;
798
799 for (i = 0; attr->name[i] && nameptr < (name + sizeof(name) - 1); i ++)
800 if (attr->name[i] == '-')
801 *nameptr++ = '_';
802 else
803 *nameptr++ = attr->name[i];
804
805 *nameptr = '\0';
806
807 /*
808 * Add "job_printer_name" variable if we have a "job_printer_uri"
809 * attribute...
810 */
811
812 if (!strcmp(name, "job_printer_uri"))
813 {
814 if ((valptr = strrchr(attr->values[0].string.text, '/')) == NULL)
815 valptr = "unknown";
816 else
817 valptr ++;
818
819 cgiSetArray("job_printer_name", element, valptr);
820 }
821
f7deaa1a 822 /*
823 * Localize event names in "notify_events" variable...
824 */
825
826 if (!strcmp(name, "notify_events"))
827 {
828 size_t remaining; /* Remaining bytes in buffer */
829
830
831 value[0] = '\0';
832 valptr = value;
833
834 for (i = 0; i < attr->num_values; i ++)
835 {
836 if (valptr >= (value + sizeof(value) - 3))
837 break;
838
839 if (i)
840 {
841 *valptr++ = ',';
842 *valptr++ = ' ';
843 }
844
845 remaining = sizeof(value) - (valptr - value);
846
847 if (!strcmp(attr->values[i].string.text, "printer-stopped"))
848 strlcpy(valptr, _("Printer Stopped"), remaining);
849 else if (!strcmp(attr->values[i].string.text, "printer-added"))
850 strlcpy(valptr, _("Printer Added"), remaining);
851 else if (!strcmp(attr->values[i].string.text, "printer-modified"))
852 strlcpy(valptr, _("Printer Modified"), remaining);
853 else if (!strcmp(attr->values[i].string.text, "printer-deleted"))
854 strlcpy(valptr, _("Printer Deleted"), remaining);
855 else if (!strcmp(attr->values[i].string.text, "job-created"))
856 strlcpy(valptr, _("Job Created"), remaining);
857 else if (!strcmp(attr->values[i].string.text, "job-completed"))
858 strlcpy(valptr, _("Job Completed"), remaining);
859 else if (!strcmp(attr->values[i].string.text, "job-stopped"))
860 strlcpy(valptr, _("Job Stopped"), remaining);
861 else if (!strcmp(attr->values[i].string.text, "job-config-changed"))
862 strlcpy(valptr, _("Job Options Changed"), remaining);
863 else if (!strcmp(attr->values[i].string.text, "server-restarted"))
864 strlcpy(valptr, _("Server Restarted"), remaining);
865 else if (!strcmp(attr->values[i].string.text, "server-started"))
866 strlcpy(valptr, _("Server Started"), remaining);
867 else if (!strcmp(attr->values[i].string.text, "server-stopped"))
868 strlcpy(valptr, _("Server Stopped"), remaining);
869 else if (!strcmp(attr->values[i].string.text, "server-audit"))
870 strlcpy(valptr, _("Server Security Auditing"), remaining);
871 else
872 strlcpy(valptr, attr->values[i].string.text, remaining);
873
874 valptr += strlen(valptr);
875 }
876
877 cgiSetArray("notify_events", element, value);
878 continue;
879 }
880
881 /*
882 * Add "notify_printer_name" variable if we have a "notify_printer_uri"
883 * attribute...
884 */
885
886 if (!strcmp(name, "notify_printer_uri"))
887 {
888 if ((valptr = strrchr(attr->values[0].string.text, '/')) == NULL)
889 valptr = "unknown";
890 else
891 valptr ++;
892
893 cgiSetArray("notify_printer_name", element, valptr);
894 }
895
896 /*
897 * Add "notify_recipient_name" variable if we have a "notify_recipient_uri"
898 * attribute, and rewrite recipient URI...
899 */
900
901 if (!strcmp(name, "notify_recipient_uri"))
902 {
903 char uri[1024], /* New URI */
904 scheme[32], /* Scheme portion of URI */
905 userpass[256], /* Username/password portion of URI */
906 host[1024], /* Hostname portion of URI */
907 resource[1024], /* Resource portion of URI */
908 *options; /* Options in URI */
909 int port; /* Port number */
910
911
912 httpSeparateURI(HTTP_URI_CODING_ALL, attr->values[0].string.text,
913 scheme, sizeof(scheme), userpass, sizeof(userpass),
914 host, sizeof(host), &port, resource, sizeof(resource));
915
916 if (!strcmp(scheme, "rss"))
917 {
918 /*
919 * RSS notification...
920 */
921
922 if ((options = strchr(resource, '?')) != NULL)
923 *options = '\0';
924
925 if (host[0])
926 {
927 /*
928 * Link to remote feed...
929 */
930
931 httpAssembleURI(HTTP_URI_CODING_ALL, uri, sizeof(uri), "http",
932 userpass, host, port, resource);
933 strlcpy(name, uri, sizeof(name));
934 }
935 else
936 {
937 /*
938 * Link to local feed...
939 */
940
941 snprintf(uri, sizeof(uri), "/rss%s", resource);
942 strlcpy(name, resource + 1, sizeof(name));
943 }
944 }
945 else
946 {
947 /*
948 * Other...
949 */
950
951 strlcpy(uri, attr->values[0].string.text, sizeof(uri));
952 strlcpy(name, resource, sizeof(name));
953 }
954
955 cgiSetArray("notify_recipient_uri", element, uri);
956 cgiSetArray("notify_recipient_name", element, name);
957 continue;
958 }
959
ef416fc2 960 /*
961 * Add "admin_uri" variable if we have a "printer_uri_supported"
962 * attribute...
963 */
964
965 if (!strcmp(name, "printer_uri_supported"))
966 {
967 cgiRewriteURL(attr->values[0].string.text, value, sizeof(value),
968 "/admin/");
969
970 cgiSetArray("admin_uri", element, value);
971 }
972
973 /*
974 * Copy values...
975 */
976
977 value[0] = '\0'; /* Initially an empty string */
978 valptr = value; /* Start at the beginning */
979
980 for (i = 0; i < attr->num_values; i ++)
981 {
982 if (i)
2e4ff8af 983 strlcat(valptr, ", ", sizeof(value) - (valptr - value));
ef416fc2 984
985 valptr += strlen(valptr);
986
987 switch (attr->value_tag)
988 {
989 case IPP_TAG_INTEGER :
990 case IPP_TAG_ENUM :
991 if (strncmp(name, "time_at_", 8) == 0)
992 {
993 time_t t; /* Temporary time value */
994
995 t = (time_t)attr->values[i].integer;
996 date = localtime(&t);
997
998 strftime(valptr, sizeof(value) - (valptr - value), "%c", date);
999 }
1000 else
1001 snprintf(valptr, sizeof(value) - (valptr - value),
1002 "%d", attr->values[i].integer);
1003 break;
1004
1005 case IPP_TAG_BOOLEAN :
1006 snprintf(valptr, sizeof(value) - (valptr - value),
1007 "%d", attr->values[i].boolean);
1008 break;
1009
1010 case IPP_TAG_NOVALUE :
1011 strlcat(valptr, "novalue", sizeof(value) - (valptr - value));
1012 break;
1013
1014 case IPP_TAG_RANGE :
1015 snprintf(valptr, sizeof(value) - (valptr - value),
1016 "%d-%d", attr->values[i].range.lower,
1017 attr->values[i].range.upper);
1018 break;
1019
1020 case IPP_TAG_RESOLUTION :
1021 snprintf(valptr, sizeof(value) - (valptr - value),
1022 "%dx%d%s", attr->values[i].resolution.xres,
1023 attr->values[i].resolution.yres,
1024 attr->values[i].resolution.units == IPP_RES_PER_INCH ?
1025 "dpi" : "dpc");
1026 break;
1027
1028 case IPP_TAG_URI :
b423cd4c 1029 if (strchr(attr->values[i].string.text, ':') &&
1030 strcmp(name, "device_uri"))
ef416fc2 1031 {
1032 /*
1033 * Rewrite URIs...
1034 */
1035
1036 if (!strcmp(name, "member_uris"))
1037 {
1038 char url[1024]; /* URL for class member... */
1039
1040
1041 cgiRewriteURL(attr->values[i].string.text, url,
1042 sizeof(url), NULL);
1043
1044 snprintf(valptr, sizeof(value) - (valptr - value),
1045 "<A HREF=\"%s\">%s</A>", url,
b86bc4cf 1046 strrchr(attr->values[i].string.text, '/') + 1);
ef416fc2 1047 }
1048 else
1049 cgiRewriteURL(attr->values[i].string.text, valptr,
1050 sizeof(value) - (valptr - value), NULL);
1051 break;
1052 }
1053
1054 case IPP_TAG_STRING :
1055 case IPP_TAG_TEXT :
1056 case IPP_TAG_NAME :
1057 case IPP_TAG_KEYWORD :
1058 case IPP_TAG_CHARSET :
1059 case IPP_TAG_LANGUAGE :
1060 case IPP_TAG_MIMETYPE :
1061 strlcat(valptr, attr->values[i].string.text,
1062 sizeof(value) - (valptr - value));
1063 break;
1064
1065 case IPP_TAG_BEGIN_COLLECTION :
1066 snprintf(value, sizeof(value), "%s%d", name, i + 1);
1067 cgiSetIPPVars(attr->values[i].collection, NULL, NULL, value,
1068 element);
1069 break;
1070
1071 default :
1072 break; /* anti-compiler-warning-code */
1073 }
1074 }
1075
1076 /*
1077 * Add the element...
1078 */
1079
1080 if (attr->value_tag != IPP_TAG_BEGIN_COLLECTION)
1081 {
1082 cgiSetArray(name, element, value);
1083
1084 fprintf(stderr, "DEBUG2: %s[%d]=\"%s\"\n", name, element, value);
1085 }
1086 }
1087
1088 return (attr ? attr->next : NULL);
1089}
1090
1091
1092/*
1093 * 'cgiSetIPPVars()' - Set CGI variables from an IPP response.
1094 */
1095
1096int /* O - Maximum number of elements */
1097cgiSetIPPVars(ipp_t *response, /* I - Response data to be copied... */
1098 const char *filter_name, /* I - Filter name */
1099 const char *filter_value, /* I - Filter value */
1100 const char *prefix, /* I - Prefix for name or NULL */
1101 int parent_el) /* I - Parent element number */
1102{
1103 int element; /* Element in CGI array */
1104 ipp_attribute_t *attr, /* Attribute in response... */
1105 *filter; /* Filtering attribute */
1106
1107
1108 fprintf(stderr, "DEBUG2: cgiSetIPPVars(response=%p, filter_name=\"%s\", "
1109 "filter_value=\"%s\", prefix=\"%s\", parent_el=%d)\n",
f301802f 1110 response, filter_name ? filter_name : "(null)",
1111 filter_value ? filter_value : "(null)",
1112 prefix ? prefix : "(null)", parent_el);
ef416fc2 1113
1114 /*
1115 * Set common CGI template variables...
1116 */
1117
1118 if (!prefix)
1119 cgiSetServerVersion();
1120
1121 /*
1122 * Loop through the attributes and set them for the template...
1123 */
1124
1125 attr = response->attrs;
1126
1127 if (!prefix)
1128 while (attr && attr->group_tag == IPP_TAG_OPERATION)
1129 attr = attr->next;
1130
1131 for (element = parent_el; attr; element ++)
1132 {
1133 /*
1134 * Copy attributes to a separator...
1135 */
1136
1137 while (attr && attr->group_tag == IPP_TAG_ZERO)
1138 attr= attr->next;
1139
1140 if (!attr)
1141 break;
1142
1143 if (filter_name)
1144 {
1145 for (filter = attr;
1146 filter != NULL && filter->group_tag != IPP_TAG_ZERO;
1147 filter = filter->next)
1148 if (filter->name && !strcmp(filter->name, filter_name) &&
1149 (filter->value_tag == IPP_TAG_STRING ||
1150 (filter->value_tag >= IPP_TAG_TEXTLANG &&
1151 filter->value_tag <= IPP_TAG_MIMETYPE)) &&
1152 filter->values[0].string.text != NULL &&
1153 !strcasecmp(filter->values[0].string.text, filter_value))
1154 break;
1155
1156 if (!filter)
1157 return (element + 1);
1158
1159 if (filter->group_tag == IPP_TAG_ZERO)
1160 {
1161 attr = filter;
1162 element --;
1163 continue;
1164 }
1165 }
1166
1167 attr = cgiSetIPPObjectVars(attr, prefix, element);
1168 }
1169
89d46774 1170 fprintf(stderr, "DEBUG2: Returing %d from cgiSetIPPVars()...\n", element);
ef416fc2 1171
89d46774 1172 return (element);
ef416fc2 1173}
1174
1175
fa73b229 1176/*
1177 * 'cgiShowIPPError()' - Show the last IPP error message.
1178 *
1179 * The caller must still call cgiStartHTML() and cgiEndHTML().
1180 */
1181
1182void
1183cgiShowIPPError(const char *message) /* I - Contextual message */
1184{
1185 cgiSetVariable("MESSAGE", cgiText(message));
1186 cgiSetVariable("ERROR", cupsLastErrorString());
1187 cgiCopyTemplateLang("error.tmpl");
1188}
1189
1190
ef416fc2 1191/*
1192 * 'cgiShowJobs()' - Show print jobs.
1193 */
1194
1195void
1196cgiShowJobs(http_t *http, /* I - Connection to server */
1197 const char *dest) /* I - Destination name or NULL */
1198{
1199 int i; /* Looping var */
1200 const char *which_jobs; /* Which jobs to show */
1201 ipp_t *request, /* IPP request */
1202 *response; /* IPP response */
1203 cups_array_t *jobs; /* Array of job objects */
1204 ipp_attribute_t *job; /* Job object */
1205 int ascending, /* Order of jobs (0 = descending) */
1206 first, /* First job to show */
1207 count; /* Number of jobs */
1208 const char *var; /* Form variable */
1209 void *search; /* Search data */
2e4ff8af
MS
1210 char url[1024], /* Printer URI */
1211 val[1024]; /* Form variable */
ef416fc2 1212
1213
1214 /*
1215 * Build an IPP_GET_JOBS request, which requires the following
1216 * attributes:
1217 *
1218 * attributes-charset
1219 * attributes-natural-language
1220 * printer-uri
1221 */
1222
fa73b229 1223 request = ippNewRequest(IPP_GET_JOBS);
ef416fc2 1224
1225 if (dest)
1226 {
a4d04587 1227 httpAssembleURIf(HTTP_URI_CODING_ALL, url, sizeof(url), "ipp", NULL,
1228 "localhost", ippPort(), "/printers/%s", dest);
ef416fc2 1229 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
1230 NULL, url);
1231 }
1232 else
1233 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri", NULL,
1234 "ipp://localhost/jobs");
1235
1236 if ((which_jobs = cgiGetVariable("which_jobs")) != NULL)
1237 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, "which-jobs",
1238 NULL, which_jobs);
1239
1240 cgiGetAttributes(request, "jobs.tmpl");
1241
1242 /*
1243 * Do the request and get back a response...
1244 */
1245
1246 if ((response = cupsDoRequest(http, request, "/")) != NULL)
1247 {
1248 /*
1249 * Get a list of matching job objects.
1250 */
1251
2e4ff8af
MS
1252 if ((var = cgiGetVariable("QUERY")) != NULL &&
1253 !cgiGetVariable("CLEAR"))
ef416fc2 1254 search = cgiCompileSearch(var);
1255 else
1256 search = NULL;
1257
1258 jobs = cgiGetIPPObjects(response, search);
1259 count = cupsArrayCount(jobs);
1260
1261 if (search)
1262 cgiFreeSearch(search);
1263
1264 /*
1265 * Figure out which jobs to display...
1266 */
1267
1268 if ((var = cgiGetVariable("FIRST")) != NULL)
1269 first = atoi(var);
1270 else
1271 first = 0;
1272
1273 if (first >= count)
1274 first = count - CUPS_PAGE_MAX;
1275
1276 first = (first / CUPS_PAGE_MAX) * CUPS_PAGE_MAX;
1277
1278 if (first < 0)
1279 first = 0;
1280
2e4ff8af
MS
1281 sprintf(val, "%d", count);
1282 cgiSetVariable("TOTAL", val);
ef416fc2 1283
1284 if ((var = cgiGetVariable("ORDER")) != NULL)
1285 ascending = !strcasecmp(var, "asc");
1286 else
b423cd4c 1287 {
1288 ascending = !which_jobs || !strcasecmp(which_jobs, "not-completed");
1289 cgiSetVariable("ORDER", ascending ? "asc" : "dec");
1290 }
ef416fc2 1291
1292 if (ascending)
1293 {
1294 for (i = 0, job = (ipp_attribute_t *)cupsArrayIndex(jobs, first);
1295 i < CUPS_PAGE_MAX && job;
1296 i ++, job = (ipp_attribute_t *)cupsArrayNext(jobs))
1297 cgiSetIPPObjectVars(job, NULL, i);
1298 }
1299 else
1300 {
1301 for (i = 0, job = (ipp_attribute_t *)cupsArrayIndex(jobs, count - first - 1);
1302 i < CUPS_PAGE_MAX && job;
1303 i ++, job = (ipp_attribute_t *)cupsArrayPrev(jobs))
1304 cgiSetIPPObjectVars(job, NULL, i);
1305 }
1306
1307 /*
1308 * Save navigation URLs...
1309 */
1310
2e4ff8af
MS
1311 if (dest)
1312 snprintf(val, sizeof(val), "/%s/%s", cgiGetVariable("SECTION"), dest);
ef416fc2 1313 else
2e4ff8af 1314 strlcpy(val, "/jobs/", sizeof(val));
ef416fc2 1315
2e4ff8af 1316 cgiSetVariable("THISURL", val);
ef416fc2 1317
1318 if (first > 0)
1319 {
2e4ff8af
MS
1320 sprintf(val, "%d", first - CUPS_PAGE_MAX);
1321 cgiSetVariable("PREV", val);
ef416fc2 1322 }
1323
1324 if ((first + CUPS_PAGE_MAX) < count)
1325 {
2e4ff8af
MS
1326 sprintf(val, "%d", first + CUPS_PAGE_MAX);
1327 cgiSetVariable("NEXT", val);
ef416fc2 1328 }
1329
1330 /*
1331 * Then show everything...
1332 */
1333
fa73b229 1334 if (dest)
1335 cgiSetVariable("SEARCH_DEST", dest);
1336
1337 cgiCopyTemplateLang("search.tmpl");
ef416fc2 1338
1339 cgiCopyTemplateLang("jobs-header.tmpl");
1340
fa73b229 1341 if (count > 0)
1342 cgiCopyTemplateLang("pager.tmpl");
ef416fc2 1343
1344 cgiCopyTemplateLang("jobs.tmpl");
1345
fa73b229 1346 if (count > 0)
1347 cgiCopyTemplateLang("pager.tmpl");
ef416fc2 1348
bd7854cb 1349 cupsArrayDelete(jobs);
ef416fc2 1350 ippDelete(response);
1351 }
1352}
1353
1354
fa73b229 1355/*
1356 * 'cgiText()' - Return localized text.
1357 */
1358
1359const char * /* O - Localized message */
1360cgiText(const char *message) /* I - Message */
1361{
1362 static cups_lang_t *language = NULL;
1363 /* Language */
1364
1365
1366 if (!language)
1367 language = cupsLangDefault();
1368
1369 return (_cupsLangString(language, message));
1370}
1371
ef416fc2 1372
1373/*
2e4ff8af 1374 * End of "$Id: ipp-var.c 6889 2007-08-29 22:23:35Z mike $".
ef416fc2 1375 */