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