]> 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/*
757d2cad 2 * "$Id: ipp-var.c 5235 2006-03-06 13:02:23Z 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
a4d04587 460 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
461 "localhost", ippPort(), "/%s/%s",
462 cgiGetVariable("SECTION"), dest);
fa73b229 463 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
464 NULL, uri);
465 }
466
467 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-printer-uri",
468 NULL, job_printer_uri);
469
470 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
471 "requesting-user-name", NULL, user);
472
473 ippDelete(cupsDoRequest(http, request, resource));
474
475 /*
476 * Show the results...
477 */
478
479 job_printer_name = strrchr(job_printer_uri, '/') + 1;
480
481 if (cupsLastError() <= IPP_OK_CONFLICT)
482 {
483 cgiRewriteURL(job_printer_uri, resource, sizeof(resource), NULL);
484 cgiFormEncode(uri, resource, sizeof(uri));
485 snprintf(refresh, sizeof(refresh), "2;%s", uri);
486 cgiSetVariable("refresh_page", refresh);
487 }
488
489 if (job_id)
490 cgiStartHTML(cgiText(_("Move Job")));
491 else
492 cgiStartHTML(cgiText(_("Move All Jobs")));
493
494 if (cupsLastError() > IPP_OK_CONFLICT)
495 {
496 if (job_id)
497 cgiShowIPPError(_("Unable to move job"));
498 else
499 cgiShowIPPError(_("Unable to move jobs"));
500 }
501 else
502 {
503 cgiSetVariable("JOB_PRINTER_NAME", job_printer_name);
504 cgiCopyTemplateLang("job-moved.tmpl");
505 }
506 }
507
508 cgiEndHTML();
509}
510
511
512/*
513 * 'cgiPrintTestPage()' - Print a test page.
514 */
515
516void
517cgiPrintTestPage(http_t *http, /* I - Connection to server */
518 const char *dest) /* I - Destination printer/class */
519{
520 ipp_t *request, /* IPP request */
521 *response; /* IPP response */
522 char uri[HTTP_MAX_URI], /* Printer URI */
523 resource[1024], /* POST resource path */
524 refresh[1024], /* Refresh URL */
525 filename[1024]; /* Test page filename */
526 const char *datadir; /* CUPS_DATADIR env var */
527 const char *user; /* Username */
528
529
530 /*
531 * See who is logged in...
532 */
533
534 if ((user = getenv("REMOTE_USER")) == NULL)
535 user = "guest";
536
537 /*
538 * Locate the test page file...
539 */
540
541 if ((datadir = getenv("CUPS_DATADIR")) == NULL)
542 datadir = CUPS_DATADIR;
543
544 snprintf(filename, sizeof(filename), "%s/data/testprint.ps", datadir);
545
546 /*
547 * Point to the printer/class...
548 */
549
550 snprintf(resource, sizeof(resource), "/%s/%s", cgiGetVariable("SECTION"),
551 dest);
552
a4d04587 553 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
554 "localhost", ippPort(), "/%s/%s", cgiGetVariable("SECTION"),
555 dest);
fa73b229 556
557 /*
558 * Build an IPP_PRINT_JOB request, which requires the following
559 * attributes:
560 *
561 * attributes-charset
562 * attributes-natural-language
563 * printer-uri
564 * requesting-user-name
565 * document-format
566 */
567
568 request = ippNewRequest(IPP_PRINT_JOB);
569
570 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
571 NULL, uri);
572
573 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
574 "requesting-user-name", NULL, user);
575
576 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "job-name",
577 NULL, "Test Page");
578
579 ippAddString(request, IPP_TAG_JOB, IPP_TAG_MIMETYPE, "document-format",
580 NULL, "application/postscript");
581
582 /*
583 * Do the request and get back a response...
584 */
585
586 if ((response = cupsDoFileRequest(http, request, resource,
587 filename)) != NULL)
588 {
589 cgiSetIPPVars(response, NULL, NULL, NULL, 0);
590
591 ippDelete(response);
592 }
593
594 if (cupsLastError() <= IPP_OK_CONFLICT)
595 {
596 /*
597 * Automatically reload the printer status page...
598 */
599
600 cgiFormEncode(uri, resource, sizeof(uri));
601 snprintf(refresh, sizeof(refresh), "2;%s", uri);
602 cgiSetVariable("refresh_page", refresh);
603 }
604
605 cgiStartHTML(cgiText(_("Print Test Page")));
606
607 if (cupsLastError() > IPP_OK_CONFLICT)
608 cgiShowIPPError(_("Unable to print test page:"));
609 else
610 {
611 cgiSetVariable("PRINTER_NAME", dest);
612
613 cgiCopyTemplateLang("test-page.tmpl");
614 }
615
616 cgiEndHTML();
617}
618
619
ef416fc2 620/*
621 * 'cgiRewriteURL()' - Rewrite a printer URI into a web browser URL...
622 */
623
624char * /* O - New URL */
625cgiRewriteURL(const char *uri, /* I - Current URI */
626 char *url, /* O - New URL */
627 int urlsize, /* I - Size of URL buffer */
628 const char *newresource) /* I - Replacement resource */
629{
630 char method[HTTP_MAX_URI],
631 userpass[HTTP_MAX_URI],
632 hostname[HTTP_MAX_URI],
633 rawresource[HTTP_MAX_URI],
634 resource[HTTP_MAX_URI],
635 /* URI components... */
636 *rawptr, /* Pointer into rawresource */
637 *resptr; /* Pointer into resource */
638 int port; /* Port number */
639 static int ishttps = -1; /* Using encryption? */
640 static const char *server; /* Name of server */
641 static char servername[1024];
642 /* Local server name */
643 static const char hexchars[] = "0123456789ABCDEF";
644 /* Hexadecimal conversion characters */
645
646
647 /*
648 * Check if we have been called before...
649 */
650
651 if (ishttps < 0)
652 {
653 /*
654 * No, initialize static vars for the conversion...
655 *
656 * First get the server name associated with the client interface as
657 * well as the locally configured hostname. We'll check *both* of
658 * these to see if the printer URL is local...
659 */
660
661 if ((server = getenv("SERVER_NAME")) == NULL)
662 server = "";
663
757d2cad 664 httpGetHostname(NULL, servername, sizeof(servername));
ef416fc2 665
666 /*
667 * Then flag whether we are using SSL on this connection...
668 */
669
670 ishttps = getenv("HTTPS") != NULL;
671 }
672
673 /*
674 * Convert the URI to a URL...
675 */
676
a4d04587 677 httpSeparateURI(HTTP_URI_CODING_ALL, uri, method, sizeof(method), userpass,
678 sizeof(userpass), hostname, sizeof(hostname), &port,
ef416fc2 679 rawresource, sizeof(rawresource));
680
681 if (!strcmp(method, "ipp") ||
682 !strcmp(method, "http") ||
683 !strcmp(method, "https"))
684 {
685 if (newresource)
686 {
687 /*
688 * Force the specified resource name instead of the one in the URL...
689 */
690
691 strlcpy(resource, newresource, sizeof(resource));
692 }
693 else
694 {
695 /*
696 * Rewrite the resource string so it doesn't contain any
697 * illegal chars...
698 */
699
700 for (rawptr = rawresource, resptr = resource; *rawptr; rawptr ++)
701 if ((*rawptr & 128) || *rawptr == '%' || *rawptr == ' ' ||
702 *rawptr == '#' || *rawptr == '?' ||
703 *rawptr == '.') /* For MSIE */
704 {
705 if (resptr < (resource + sizeof(resource) - 3))
706 {
707 *resptr++ = '%';
708 *resptr++ = hexchars[(*rawptr >> 4) & 15];
709 *resptr++ = hexchars[*rawptr & 15];
710 }
711 }
712 else if (resptr < (resource + sizeof(resource) - 1))
713 *resptr++ = *rawptr;
714
715 *resptr = '\0';
716 }
717
718 /*
719 * Map local access to a local URI...
720 */
721
722 if (!strcasecmp(hostname, "localhost") ||
723 !strncasecmp(hostname, "localhost.", 10) ||
724 !strcasecmp(hostname, server) ||
725 !strcasecmp(hostname, servername))
726 {
727 /*
728 * Make URI relative to the current server...
729 */
730
731 strlcpy(url, resource, urlsize);
732 }
733 else
734 {
735 /*
736 * Rewrite URI with HTTP/HTTPS scheme...
737 */
738
739 if (userpass[0])
740 snprintf(url, urlsize, "%s://%s@%s:%d%s",
741 ishttps ? "https" : "http",
742 userpass, hostname, port, resource);
743 else
744 snprintf(url, urlsize, "%s://%s:%d%s",
745 ishttps ? "https" : "http",
746 hostname, port, resource);
747 }
748 }
749 else
750 strlcpy(url, uri, urlsize);
751
752 return (url);
753}
754
755
756/*
757 * 'cgiSetIPPObjectVars()' - Set CGI variables from an IPP object.
758 */
759
760ipp_attribute_t * /* O - Next object */
761cgiSetIPPObjectVars(
762 ipp_attribute_t *obj, /* I - Response data to be copied... */
763 const char *prefix, /* I - Prefix for name or NULL */
764 int element) /* I - Parent element number */
765{
766 ipp_attribute_t *attr; /* Attribute in response... */
767 int i; /* Looping var */
768 char name[1024], /* Name of attribute */
769 *nameptr, /* Pointer into name */
770 value[16384], /* Value(s) */
771 *valptr; /* Pointer into value */
772 struct tm *date; /* Date information */
773
774
775 fprintf(stderr, "DEBUG2: cgiSetIPPObjectVars(obj=%p, prefix=\"%s\", "
776 "element=%d)\n",
777 obj, prefix, element);
778
779 /*
780 * Set common CGI template variables...
781 */
782
783 if (!prefix)
784 cgiSetServerVersion();
785
786 /*
787 * Loop through the attributes and set them for the template...
788 */
789
790 for (attr = obj; attr && attr->group_tag != IPP_TAG_ZERO; attr = attr->next)
791 {
792 /*
793 * Copy the attribute name, substituting "_" for "-"...
794 */
795
796 if (!attr->name)
797 continue;
798
799 if (prefix)
800 {
801 snprintf(name, sizeof(name), "%s.", prefix);
802 nameptr = name + strlen(name);
803 }
804 else
805 nameptr = name;
806
807 for (i = 0; attr->name[i] && nameptr < (name + sizeof(name) - 1); i ++)
808 if (attr->name[i] == '-')
809 *nameptr++ = '_';
810 else
811 *nameptr++ = attr->name[i];
812
813 *nameptr = '\0';
814
815 /*
816 * Add "job_printer_name" variable if we have a "job_printer_uri"
817 * attribute...
818 */
819
820 if (!strcmp(name, "job_printer_uri"))
821 {
822 if ((valptr = strrchr(attr->values[0].string.text, '/')) == NULL)
823 valptr = "unknown";
824 else
825 valptr ++;
826
827 cgiSetArray("job_printer_name", element, valptr);
828 }
829
830 /*
831 * Add "admin_uri" variable if we have a "printer_uri_supported"
832 * attribute...
833 */
834
835 if (!strcmp(name, "printer_uri_supported"))
836 {
837 cgiRewriteURL(attr->values[0].string.text, value, sizeof(value),
838 "/admin/");
839
840 cgiSetArray("admin_uri", element, value);
841 }
842
843 /*
844 * Copy values...
845 */
846
847 value[0] = '\0'; /* Initially an empty string */
848 valptr = value; /* Start at the beginning */
849
850 for (i = 0; i < attr->num_values; i ++)
851 {
852 if (i)
853 strlcat(valptr, ",", sizeof(value) - (valptr - value));
854
855 valptr += strlen(valptr);
856
857 switch (attr->value_tag)
858 {
859 case IPP_TAG_INTEGER :
860 case IPP_TAG_ENUM :
861 if (strncmp(name, "time_at_", 8) == 0)
862 {
863 time_t t; /* Temporary time value */
864
865 t = (time_t)attr->values[i].integer;
866 date = localtime(&t);
867
868 strftime(valptr, sizeof(value) - (valptr - value), "%c", date);
869 }
870 else
871 snprintf(valptr, sizeof(value) - (valptr - value),
872 "%d", attr->values[i].integer);
873 break;
874
875 case IPP_TAG_BOOLEAN :
876 snprintf(valptr, sizeof(value) - (valptr - value),
877 "%d", attr->values[i].boolean);
878 break;
879
880 case IPP_TAG_NOVALUE :
881 strlcat(valptr, "novalue", sizeof(value) - (valptr - value));
882 break;
883
884 case IPP_TAG_RANGE :
885 snprintf(valptr, sizeof(value) - (valptr - value),
886 "%d-%d", attr->values[i].range.lower,
887 attr->values[i].range.upper);
888 break;
889
890 case IPP_TAG_RESOLUTION :
891 snprintf(valptr, sizeof(value) - (valptr - value),
892 "%dx%d%s", attr->values[i].resolution.xres,
893 attr->values[i].resolution.yres,
894 attr->values[i].resolution.units == IPP_RES_PER_INCH ?
895 "dpi" : "dpc");
896 break;
897
898 case IPP_TAG_URI :
b423cd4c 899 if (strchr(attr->values[i].string.text, ':') &&
900 strcmp(name, "device_uri"))
ef416fc2 901 {
902 /*
903 * Rewrite URIs...
904 */
905
906 if (!strcmp(name, "member_uris"))
907 {
908 char url[1024]; /* URL for class member... */
909
910
911 cgiRewriteURL(attr->values[i].string.text, url,
912 sizeof(url), NULL);
913
914 snprintf(valptr, sizeof(value) - (valptr - value),
915 "<A HREF=\"%s\">%s</A>", url,
916 strrchr(url, '/') + 1);
917 }
918 else
919 cgiRewriteURL(attr->values[i].string.text, valptr,
920 sizeof(value) - (valptr - value), NULL);
921 break;
922 }
923
924 case IPP_TAG_STRING :
925 case IPP_TAG_TEXT :
926 case IPP_TAG_NAME :
927 case IPP_TAG_KEYWORD :
928 case IPP_TAG_CHARSET :
929 case IPP_TAG_LANGUAGE :
930 case IPP_TAG_MIMETYPE :
931 strlcat(valptr, attr->values[i].string.text,
932 sizeof(value) - (valptr - value));
933 break;
934
935 case IPP_TAG_BEGIN_COLLECTION :
936 snprintf(value, sizeof(value), "%s%d", name, i + 1);
937 cgiSetIPPVars(attr->values[i].collection, NULL, NULL, value,
938 element);
939 break;
940
941 default :
942 break; /* anti-compiler-warning-code */
943 }
944 }
945
946 /*
947 * Add the element...
948 */
949
950 if (attr->value_tag != IPP_TAG_BEGIN_COLLECTION)
951 {
952 cgiSetArray(name, element, value);
953
954 fprintf(stderr, "DEBUG2: %s[%d]=\"%s\"\n", name, element, value);
955 }
956 }
957
958 return (attr ? attr->next : NULL);
959}
960
961
962/*
963 * 'cgiSetIPPVars()' - Set CGI variables from an IPP response.
964 */
965
966int /* O - Maximum number of elements */
967cgiSetIPPVars(ipp_t *response, /* I - Response data to be copied... */
968 const char *filter_name, /* I - Filter name */
969 const char *filter_value, /* I - Filter value */
970 const char *prefix, /* I - Prefix for name or NULL */
971 int parent_el) /* I - Parent element number */
972{
973 int element; /* Element in CGI array */
974 ipp_attribute_t *attr, /* Attribute in response... */
975 *filter; /* Filtering attribute */
976
977
978 fprintf(stderr, "DEBUG2: cgiSetIPPVars(response=%p, filter_name=\"%s\", "
979 "filter_value=\"%s\", prefix=\"%s\", parent_el=%d)\n",
980 response, filter_name, filter_value, prefix, parent_el);
981
982 /*
983 * Set common CGI template variables...
984 */
985
986 if (!prefix)
987 cgiSetServerVersion();
988
989 /*
990 * Loop through the attributes and set them for the template...
991 */
992
993 attr = response->attrs;
994
995 if (!prefix)
996 while (attr && attr->group_tag == IPP_TAG_OPERATION)
997 attr = attr->next;
998
999 for (element = parent_el; attr; element ++)
1000 {
1001 /*
1002 * Copy attributes to a separator...
1003 */
1004
1005 while (attr && attr->group_tag == IPP_TAG_ZERO)
1006 attr= attr->next;
1007
1008 if (!attr)
1009 break;
1010
1011 if (filter_name)
1012 {
1013 for (filter = attr;
1014 filter != NULL && filter->group_tag != IPP_TAG_ZERO;
1015 filter = filter->next)
1016 if (filter->name && !strcmp(filter->name, filter_name) &&
1017 (filter->value_tag == IPP_TAG_STRING ||
1018 (filter->value_tag >= IPP_TAG_TEXTLANG &&
1019 filter->value_tag <= IPP_TAG_MIMETYPE)) &&
1020 filter->values[0].string.text != NULL &&
1021 !strcasecmp(filter->values[0].string.text, filter_value))
1022 break;
1023
1024 if (!filter)
1025 return (element + 1);
1026
1027 if (filter->group_tag == IPP_TAG_ZERO)
1028 {
1029 attr = filter;
1030 element --;
1031 continue;
1032 }
1033 }
1034
1035 attr = cgiSetIPPObjectVars(attr, prefix, element);
1036 }
1037
1038 fprintf(stderr, "DEBUG2: Returing %d from cgiSetIPPVars()...\n", element + 1);
1039
1040 return (element + 1);
1041}
1042
1043
fa73b229 1044/*
1045 * 'cgiShowIPPError()' - Show the last IPP error message.
1046 *
1047 * The caller must still call cgiStartHTML() and cgiEndHTML().
1048 */
1049
1050void
1051cgiShowIPPError(const char *message) /* I - Contextual message */
1052{
1053 cgiSetVariable("MESSAGE", cgiText(message));
1054 cgiSetVariable("ERROR", cupsLastErrorString());
1055 cgiCopyTemplateLang("error.tmpl");
1056}
1057
1058
ef416fc2 1059/*
1060 * 'cgiShowJobs()' - Show print jobs.
1061 */
1062
1063void
1064cgiShowJobs(http_t *http, /* I - Connection to server */
1065 const char *dest) /* I - Destination name or NULL */
1066{
1067 int i; /* Looping var */
1068 const char *which_jobs; /* Which jobs to show */
1069 ipp_t *request, /* IPP request */
1070 *response; /* IPP response */
1071 cups_array_t *jobs; /* Array of job objects */
1072 ipp_attribute_t *job; /* Job object */
1073 int ascending, /* Order of jobs (0 = descending) */
1074 first, /* First job to show */
1075 count; /* Number of jobs */
1076 const char *var; /* Form variable */
1077 void *search; /* Search data */
1078 char url[1024], /* URL for prev/next/this */
1079 *urlptr, /* Position in URL */
1080 *urlend; /* End of URL */
ef416fc2 1081
1082
1083 /*
1084 * Build an IPP_GET_JOBS request, which requires the following
1085 * attributes:
1086 *
1087 * attributes-charset
1088 * attributes-natural-language
1089 * printer-uri
1090 */
1091
fa73b229 1092 request = ippNewRequest(IPP_GET_JOBS);
ef416fc2 1093
1094 if (dest)
1095 {
a4d04587 1096 httpAssembleURIf(HTTP_URI_CODING_ALL, url, sizeof(url), "ipp", NULL,
1097 "localhost", ippPort(), "/printers/%s", dest);
ef416fc2 1098 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
1099 NULL, url);
1100 }
1101 else
1102 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri", NULL,
1103 "ipp://localhost/jobs");
1104
1105 if ((which_jobs = cgiGetVariable("which_jobs")) != NULL)
1106 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, "which-jobs",
1107 NULL, which_jobs);
1108
1109 cgiGetAttributes(request, "jobs.tmpl");
1110
1111 /*
1112 * Do the request and get back a response...
1113 */
1114
1115 if ((response = cupsDoRequest(http, request, "/")) != NULL)
1116 {
1117 /*
1118 * Get a list of matching job objects.
1119 */
1120
fa73b229 1121 if ((var = cgiGetVariable("QUERY")) != NULL)
ef416fc2 1122 search = cgiCompileSearch(var);
1123 else
1124 search = NULL;
1125
1126 jobs = cgiGetIPPObjects(response, search);
1127 count = cupsArrayCount(jobs);
1128
1129 if (search)
1130 cgiFreeSearch(search);
1131
1132 /*
1133 * Figure out which jobs to display...
1134 */
1135
1136 if ((var = cgiGetVariable("FIRST")) != NULL)
1137 first = atoi(var);
1138 else
1139 first = 0;
1140
1141 if (first >= count)
1142 first = count - CUPS_PAGE_MAX;
1143
1144 first = (first / CUPS_PAGE_MAX) * CUPS_PAGE_MAX;
1145
1146 if (first < 0)
1147 first = 0;
1148
1149 sprintf(url, "%d", count);
1150 cgiSetVariable("TOTAL", url);
1151
1152 if ((var = cgiGetVariable("ORDER")) != NULL)
1153 ascending = !strcasecmp(var, "asc");
1154 else
b423cd4c 1155 {
1156 ascending = !which_jobs || !strcasecmp(which_jobs, "not-completed");
1157 cgiSetVariable("ORDER", ascending ? "asc" : "dec");
1158 }
ef416fc2 1159
1160 if (ascending)
1161 {
1162 for (i = 0, job = (ipp_attribute_t *)cupsArrayIndex(jobs, first);
1163 i < CUPS_PAGE_MAX && job;
1164 i ++, job = (ipp_attribute_t *)cupsArrayNext(jobs))
1165 cgiSetIPPObjectVars(job, NULL, i);
1166 }
1167 else
1168 {
1169 for (i = 0, job = (ipp_attribute_t *)cupsArrayIndex(jobs, count - first - 1);
1170 i < CUPS_PAGE_MAX && job;
1171 i ++, job = (ipp_attribute_t *)cupsArrayPrev(jobs))
1172 cgiSetIPPObjectVars(job, NULL, i);
1173 }
1174
1175 /*
1176 * Save navigation URLs...
1177 */
1178
1179 urlend = url + sizeof(url);
1180
fa73b229 1181 if ((var = cgiGetVariable("QUERY")) != NULL)
ef416fc2 1182 {
fa73b229 1183 if (dest)
1184 snprintf(url, sizeof(url), "/%s/%s?QUERY=", cgiGetVariable("SECTION"),
1185 dest);
1186 else
1187 strlcpy(url, "/jobs/?QUERY=", sizeof(url));
1188
ef416fc2 1189 urlptr = url + strlen(url);
1190
1191 cgiFormEncode(urlptr, var, urlend - urlptr);
1192 urlptr += strlen(urlptr);
1193
1194 strlcpy(urlptr, "&", urlend - urlptr);
1195 urlptr += strlen(urlptr);
1196 }
1197 else
1198 {
fa73b229 1199 if (dest)
1200 snprintf(url, sizeof(url), "/%s/%s?", cgiGetVariable("SECTION"), dest);
1201 else
1202 strlcpy(url, "/jobs/?", sizeof(url));
1203
ef416fc2 1204 urlptr = url + strlen(url);
1205 }
1206
1207 if (which_jobs)
1208 {
1209 strlcpy(urlptr, "WHICH_JOBS=", urlend - urlptr);
1210 urlptr += strlen(urlptr);
1211
1212 cgiFormEncode(urlptr, which_jobs, urlend - urlptr);
1213 urlptr += strlen(urlptr);
1214
1215 strlcpy(urlptr, "&", urlend - urlptr);
1216 urlptr += strlen(urlptr);
1217 }
1218
1219 snprintf(urlptr, urlend - urlptr, "FIRST=%d", first);
1220 cgiSetVariable("THISURL", url);
1221
1222 if (first > 0)
1223 {
1224 snprintf(urlptr, urlend - urlptr, "FIRST=%d&ORDER=%s",
1225 first - CUPS_PAGE_MAX, ascending ? "asc" : "dec");
1226 cgiSetVariable("PREVURL", url);
1227 }
1228
1229 if ((first + CUPS_PAGE_MAX) < count)
1230 {
1231 snprintf(urlptr, urlend - urlptr, "FIRST=%d&ORDER=%s",
1232 first + CUPS_PAGE_MAX, ascending ? "asc" : "dec");
1233 cgiSetVariable("NEXTURL", url);
1234 }
1235
1236 /*
1237 * Then show everything...
1238 */
1239
fa73b229 1240 if (dest)
1241 cgiSetVariable("SEARCH_DEST", dest);
1242
1243 cgiCopyTemplateLang("search.tmpl");
ef416fc2 1244
1245 cgiCopyTemplateLang("jobs-header.tmpl");
1246
fa73b229 1247 if (count > 0)
1248 cgiCopyTemplateLang("pager.tmpl");
ef416fc2 1249
1250 cgiCopyTemplateLang("jobs.tmpl");
1251
fa73b229 1252 if (count > 0)
1253 cgiCopyTemplateLang("pager.tmpl");
ef416fc2 1254
bd7854cb 1255 cupsArrayDelete(jobs);
ef416fc2 1256 ippDelete(response);
1257 }
1258}
1259
1260
fa73b229 1261/*
1262 * 'cgiText()' - Return localized text.
1263 */
1264
1265const char * /* O - Localized message */
1266cgiText(const char *message) /* I - Message */
1267{
1268 static cups_lang_t *language = NULL;
1269 /* Language */
1270
1271
1272 if (!language)
1273 language = cupsLangDefault();
1274
1275 return (_cupsLangString(language, message));
1276}
1277
ef416fc2 1278
1279/*
757d2cad 1280 * End of "$Id: ipp-var.c 5235 2006-03-06 13:02:23Z mike $".
ef416fc2 1281 */