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