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