]>
Commit | Line | Data |
---|---|---|
ef416fc2 | 1 | /* |
2 | * "$Id: ipp-var.c 4921 2006-01-12 21:26:26Z mike $" | |
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. | |
28 | * cupsGetIPPObjects() - Get the objects in an IPP response. | |
29 | * cgiRewriteURL() - Rewrite a printer URI into a web browser URL... | |
30 | * cgiSetIPPObjectVars() - Set CGI variables from an IPP object. | |
31 | * cgiSetIPPVars() - Set CGI variables from an IPP response. | |
32 | */ | |
33 | ||
34 | /* | |
35 | * Include necessary headers... | |
36 | */ | |
37 | ||
38 | #include "cgi-private.h" | |
39 | ||
40 | ||
41 | /* | |
42 | * 'cgiGetAttributes()' - Get the list of attributes that are needed | |
43 | * by the template file. | |
44 | */ | |
45 | ||
46 | void | |
47 | cgiGetAttributes(ipp_t *request, /* I - IPP request */ | |
48 | const char *tmpl) /* I - Base filename */ | |
49 | { | |
50 | int num_attrs; /* Number of attributes */ | |
51 | char *attrs[1000]; /* Attributes */ | |
52 | int i; /* Looping var */ | |
53 | char filename[1024], /* Filename */ | |
54 | locale[16]; /* Locale name */ | |
55 | const char *directory, /* Directory */ | |
56 | *lang; /* Language */ | |
57 | FILE *in; /* Input file */ | |
58 | int ch; /* Character from file */ | |
59 | char name[255], /* Name of variable */ | |
60 | *nameptr; /* Pointer into name */ | |
61 | ||
62 | ||
63 | /* | |
64 | * Convert the language to a locale name... | |
65 | */ | |
66 | ||
67 | if ((lang = getenv("LANG")) != NULL) | |
68 | { | |
69 | for (i = 0; lang[i] && i < 15; i ++) | |
70 | if (isalnum(lang[i] & 255)) | |
71 | locale[i] = tolower(lang[i]); | |
72 | else | |
73 | locale[i] = '_'; | |
74 | ||
75 | locale[i] = '\0'; | |
76 | } | |
77 | else | |
78 | locale[0] = '\0'; | |
79 | ||
80 | /* | |
81 | * See if we have a template file for this language... | |
82 | */ | |
83 | ||
84 | directory = cgiGetTemplateDir(); | |
85 | ||
86 | snprintf(filename, sizeof(filename), "%s/%s/%s", directory, locale, tmpl); | |
87 | if (access(filename, 0)) | |
88 | { | |
89 | locale[2] = '\0'; | |
90 | ||
91 | snprintf(filename, sizeof(filename), "%s/%s/%s", directory, locale, tmpl); | |
92 | if (access(filename, 0)) | |
93 | snprintf(filename, sizeof(filename), "%s/%s", directory, tmpl); | |
94 | } | |
95 | ||
96 | /* | |
97 | * Open the template file... | |
98 | */ | |
99 | ||
100 | if ((in = fopen(filename, "r")) == NULL) | |
101 | return; | |
102 | ||
103 | /* | |
104 | * Loop through the file adding attribute names as needed... | |
105 | */ | |
106 | ||
107 | num_attrs = 0; | |
108 | ||
109 | while ((ch = getc(in)) != EOF) | |
110 | if (ch == '\\') | |
111 | getc(in); | |
112 | else if (ch == '{' && num_attrs < (sizeof(attrs) / sizeof(attrs[0]))) | |
113 | { | |
114 | /* | |
115 | * Grab the name... | |
116 | */ | |
117 | ||
118 | for (nameptr = name; (ch = getc(in)) != EOF;) | |
119 | if (strchr("}]<>=! \t\n", ch)) | |
120 | break; | |
121 | else if (nameptr > name && ch == '?') | |
122 | break; | |
123 | else if (nameptr < (name + sizeof(name) - 1)) | |
124 | { | |
125 | if (ch == '_') | |
126 | *nameptr++ = '-'; | |
127 | else | |
128 | *nameptr++ = ch; | |
129 | } | |
130 | ||
131 | *nameptr = '\0'; | |
132 | ||
133 | if (!strncmp(name, "printer_state_history", 21)) | |
134 | strcpy(name, "printer_state_history"); | |
135 | ||
136 | /* | |
137 | * Possibly add it to the list of attributes... | |
138 | */ | |
139 | ||
140 | for (i = 0; i < num_attrs; i ++) | |
141 | if (!strcmp(attrs[i], name)) | |
142 | break; | |
143 | ||
144 | if (i >= num_attrs) | |
145 | { | |
146 | attrs[num_attrs] = strdup(name); | |
147 | num_attrs ++; | |
148 | } | |
149 | } | |
150 | ||
151 | /* | |
152 | * If we have attributes, add a requested-attributes attribute to the | |
153 | * request... | |
154 | */ | |
155 | ||
156 | if (num_attrs > 0) | |
157 | { | |
158 | ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, | |
159 | "requested-attributes", num_attrs, NULL, (const char **)attrs); | |
160 | ||
161 | for (i = 0; i < num_attrs; i ++) | |
162 | free(attrs[i]); | |
163 | } | |
164 | } | |
165 | ||
166 | ||
167 | /* | |
168 | * 'cupsGetIPPObjects()' - Get the objects in an IPP response. | |
169 | */ | |
170 | ||
171 | cups_array_t * /* O - Array of objects */ | |
172 | cgiGetIPPObjects(ipp_t *response, /* I - IPP response */ | |
173 | void *search) /* I - Search filter */ | |
174 | { | |
175 | int i; /* Looping var */ | |
176 | cups_array_t *objs; /* Array of objects */ | |
177 | ipp_attribute_t *attr, /* Current attribute */ | |
178 | *first; /* First attribute for object */ | |
179 | ipp_tag_t group; /* Current group tag */ | |
180 | int add; /* Add this object to the array? */ | |
181 | ||
182 | ||
183 | if (!response) | |
184 | return (0); | |
185 | ||
186 | for (add = 0, first = NULL, objs = cupsArrayNew(NULL, NULL), | |
187 | group = IPP_TAG_ZERO, attr = response->attrs; | |
188 | attr; | |
189 | attr = attr->next) | |
190 | { | |
191 | if (attr->group_tag != group) | |
192 | { | |
193 | group = attr->group_tag; | |
194 | ||
195 | if (group != IPP_TAG_ZERO && group != IPP_TAG_OPERATION) | |
196 | { | |
197 | first = attr; | |
198 | add = 0; | |
199 | } | |
200 | else if (add && first) | |
201 | { | |
202 | cupsArrayAdd(objs, first); | |
203 | ||
204 | add = 0; | |
205 | first = NULL; | |
206 | } | |
207 | } | |
208 | ||
209 | if (attr->name && attr->group_tag != IPP_TAG_OPERATION && !add) | |
210 | { | |
211 | if (!search) | |
212 | { | |
213 | /* | |
214 | * Add all objects if there is no search... | |
215 | */ | |
216 | ||
217 | add = 1; | |
218 | } | |
219 | else | |
220 | { | |
221 | /* | |
222 | * Check the search string against the string and integer values. | |
223 | */ | |
224 | ||
225 | switch (attr->value_tag) | |
226 | { | |
227 | case IPP_TAG_TEXTLANG : | |
228 | case IPP_TAG_NAMELANG : | |
229 | case IPP_TAG_TEXT : | |
230 | case IPP_TAG_NAME : | |
231 | case IPP_TAG_KEYWORD : | |
232 | case IPP_TAG_URI : | |
233 | case IPP_TAG_MIMETYPE : | |
234 | for (i = 0; !add && i < attr->num_values; i ++) | |
235 | if (cgiDoSearch(search, attr->values[i].string.text)) | |
236 | add = 1; | |
237 | break; | |
238 | ||
239 | case IPP_TAG_INTEGER : | |
240 | for (i = 0; !add && i < attr->num_values; i ++) | |
241 | { | |
242 | char buf[255]; /* Number buffer */ | |
243 | ||
244 | ||
245 | sprintf(buf, "%d", attr->values[i].integer); | |
246 | ||
247 | if (cgiDoSearch(search, buf)) | |
248 | add = 1; | |
249 | } | |
250 | break; | |
251 | ||
252 | default : | |
253 | break; | |
254 | } | |
255 | } | |
256 | } | |
257 | } | |
258 | ||
259 | if (add && first) | |
260 | cupsArrayAdd(objs, first); | |
261 | ||
262 | return (objs); | |
263 | } | |
264 | ||
265 | ||
266 | /* | |
267 | * 'cgiRewriteURL()' - Rewrite a printer URI into a web browser URL... | |
268 | */ | |
269 | ||
270 | char * /* O - New URL */ | |
271 | cgiRewriteURL(const char *uri, /* I - Current URI */ | |
272 | char *url, /* O - New URL */ | |
273 | int urlsize, /* I - Size of URL buffer */ | |
274 | const char *newresource) /* I - Replacement resource */ | |
275 | { | |
276 | char method[HTTP_MAX_URI], | |
277 | userpass[HTTP_MAX_URI], | |
278 | hostname[HTTP_MAX_URI], | |
279 | rawresource[HTTP_MAX_URI], | |
280 | resource[HTTP_MAX_URI], | |
281 | /* URI components... */ | |
282 | *rawptr, /* Pointer into rawresource */ | |
283 | *resptr; /* Pointer into resource */ | |
284 | int port; /* Port number */ | |
285 | static int ishttps = -1; /* Using encryption? */ | |
286 | static const char *server; /* Name of server */ | |
287 | static char servername[1024]; | |
288 | /* Local server name */ | |
289 | static const char hexchars[] = "0123456789ABCDEF"; | |
290 | /* Hexadecimal conversion characters */ | |
291 | ||
292 | ||
293 | /* | |
294 | * Check if we have been called before... | |
295 | */ | |
296 | ||
297 | if (ishttps < 0) | |
298 | { | |
299 | /* | |
300 | * No, initialize static vars for the conversion... | |
301 | * | |
302 | * First get the server name associated with the client interface as | |
303 | * well as the locally configured hostname. We'll check *both* of | |
304 | * these to see if the printer URL is local... | |
305 | */ | |
306 | ||
307 | if ((server = getenv("SERVER_NAME")) == NULL) | |
308 | server = ""; | |
309 | ||
310 | httpGetHostname(servername, sizeof(servername)); | |
311 | ||
312 | /* | |
313 | * Then flag whether we are using SSL on this connection... | |
314 | */ | |
315 | ||
316 | ishttps = getenv("HTTPS") != NULL; | |
317 | } | |
318 | ||
319 | /* | |
320 | * Convert the URI to a URL... | |
321 | */ | |
322 | ||
323 | httpSeparateURI(uri, method, sizeof(method), userpass, sizeof(userpass), | |
324 | hostname, sizeof(hostname), &port, | |
325 | rawresource, sizeof(rawresource)); | |
326 | ||
327 | if (!strcmp(method, "ipp") || | |
328 | !strcmp(method, "http") || | |
329 | !strcmp(method, "https")) | |
330 | { | |
331 | if (newresource) | |
332 | { | |
333 | /* | |
334 | * Force the specified resource name instead of the one in the URL... | |
335 | */ | |
336 | ||
337 | strlcpy(resource, newresource, sizeof(resource)); | |
338 | } | |
339 | else | |
340 | { | |
341 | /* | |
342 | * Rewrite the resource string so it doesn't contain any | |
343 | * illegal chars... | |
344 | */ | |
345 | ||
346 | for (rawptr = rawresource, resptr = resource; *rawptr; rawptr ++) | |
347 | if ((*rawptr & 128) || *rawptr == '%' || *rawptr == ' ' || | |
348 | *rawptr == '#' || *rawptr == '?' || | |
349 | *rawptr == '.') /* For MSIE */ | |
350 | { | |
351 | if (resptr < (resource + sizeof(resource) - 3)) | |
352 | { | |
353 | *resptr++ = '%'; | |
354 | *resptr++ = hexchars[(*rawptr >> 4) & 15]; | |
355 | *resptr++ = hexchars[*rawptr & 15]; | |
356 | } | |
357 | } | |
358 | else if (resptr < (resource + sizeof(resource) - 1)) | |
359 | *resptr++ = *rawptr; | |
360 | ||
361 | *resptr = '\0'; | |
362 | } | |
363 | ||
364 | /* | |
365 | * Map local access to a local URI... | |
366 | */ | |
367 | ||
368 | if (!strcasecmp(hostname, "localhost") || | |
369 | !strncasecmp(hostname, "localhost.", 10) || | |
370 | !strcasecmp(hostname, server) || | |
371 | !strcasecmp(hostname, servername)) | |
372 | { | |
373 | /* | |
374 | * Make URI relative to the current server... | |
375 | */ | |
376 | ||
377 | strlcpy(url, resource, urlsize); | |
378 | } | |
379 | else | |
380 | { | |
381 | /* | |
382 | * Rewrite URI with HTTP/HTTPS scheme... | |
383 | */ | |
384 | ||
385 | if (userpass[0]) | |
386 | snprintf(url, urlsize, "%s://%s@%s:%d%s", | |
387 | ishttps ? "https" : "http", | |
388 | userpass, hostname, port, resource); | |
389 | else | |
390 | snprintf(url, urlsize, "%s://%s:%d%s", | |
391 | ishttps ? "https" : "http", | |
392 | hostname, port, resource); | |
393 | } | |
394 | } | |
395 | else | |
396 | strlcpy(url, uri, urlsize); | |
397 | ||
398 | return (url); | |
399 | } | |
400 | ||
401 | ||
402 | /* | |
403 | * 'cgiSetIPPObjectVars()' - Set CGI variables from an IPP object. | |
404 | */ | |
405 | ||
406 | ipp_attribute_t * /* O - Next object */ | |
407 | cgiSetIPPObjectVars( | |
408 | ipp_attribute_t *obj, /* I - Response data to be copied... */ | |
409 | const char *prefix, /* I - Prefix for name or NULL */ | |
410 | int element) /* I - Parent element number */ | |
411 | { | |
412 | ipp_attribute_t *attr; /* Attribute in response... */ | |
413 | int i; /* Looping var */ | |
414 | char name[1024], /* Name of attribute */ | |
415 | *nameptr, /* Pointer into name */ | |
416 | value[16384], /* Value(s) */ | |
417 | *valptr; /* Pointer into value */ | |
418 | struct tm *date; /* Date information */ | |
419 | ||
420 | ||
421 | fprintf(stderr, "DEBUG2: cgiSetIPPObjectVars(obj=%p, prefix=\"%s\", " | |
422 | "element=%d)\n", | |
423 | obj, prefix, element); | |
424 | ||
425 | /* | |
426 | * Set common CGI template variables... | |
427 | */ | |
428 | ||
429 | if (!prefix) | |
430 | cgiSetServerVersion(); | |
431 | ||
432 | /* | |
433 | * Loop through the attributes and set them for the template... | |
434 | */ | |
435 | ||
436 | for (attr = obj; attr && attr->group_tag != IPP_TAG_ZERO; attr = attr->next) | |
437 | { | |
438 | /* | |
439 | * Copy the attribute name, substituting "_" for "-"... | |
440 | */ | |
441 | ||
442 | if (!attr->name) | |
443 | continue; | |
444 | ||
445 | if (prefix) | |
446 | { | |
447 | snprintf(name, sizeof(name), "%s.", prefix); | |
448 | nameptr = name + strlen(name); | |
449 | } | |
450 | else | |
451 | nameptr = name; | |
452 | ||
453 | for (i = 0; attr->name[i] && nameptr < (name + sizeof(name) - 1); i ++) | |
454 | if (attr->name[i] == '-') | |
455 | *nameptr++ = '_'; | |
456 | else | |
457 | *nameptr++ = attr->name[i]; | |
458 | ||
459 | *nameptr = '\0'; | |
460 | ||
461 | /* | |
462 | * Add "job_printer_name" variable if we have a "job_printer_uri" | |
463 | * attribute... | |
464 | */ | |
465 | ||
466 | if (!strcmp(name, "job_printer_uri")) | |
467 | { | |
468 | if ((valptr = strrchr(attr->values[0].string.text, '/')) == NULL) | |
469 | valptr = "unknown"; | |
470 | else | |
471 | valptr ++; | |
472 | ||
473 | cgiSetArray("job_printer_name", element, valptr); | |
474 | } | |
475 | ||
476 | /* | |
477 | * Add "admin_uri" variable if we have a "printer_uri_supported" | |
478 | * attribute... | |
479 | */ | |
480 | ||
481 | if (!strcmp(name, "printer_uri_supported")) | |
482 | { | |
483 | cgiRewriteURL(attr->values[0].string.text, value, sizeof(value), | |
484 | "/admin/"); | |
485 | ||
486 | cgiSetArray("admin_uri", element, value); | |
487 | } | |
488 | ||
489 | /* | |
490 | * Copy values... | |
491 | */ | |
492 | ||
493 | value[0] = '\0'; /* Initially an empty string */ | |
494 | valptr = value; /* Start at the beginning */ | |
495 | ||
496 | for (i = 0; i < attr->num_values; i ++) | |
497 | { | |
498 | if (i) | |
499 | strlcat(valptr, ",", sizeof(value) - (valptr - value)); | |
500 | ||
501 | valptr += strlen(valptr); | |
502 | ||
503 | switch (attr->value_tag) | |
504 | { | |
505 | case IPP_TAG_INTEGER : | |
506 | case IPP_TAG_ENUM : | |
507 | if (strncmp(name, "time_at_", 8) == 0) | |
508 | { | |
509 | time_t t; /* Temporary time value */ | |
510 | ||
511 | t = (time_t)attr->values[i].integer; | |
512 | date = localtime(&t); | |
513 | ||
514 | strftime(valptr, sizeof(value) - (valptr - value), "%c", date); | |
515 | } | |
516 | else | |
517 | snprintf(valptr, sizeof(value) - (valptr - value), | |
518 | "%d", attr->values[i].integer); | |
519 | break; | |
520 | ||
521 | case IPP_TAG_BOOLEAN : | |
522 | snprintf(valptr, sizeof(value) - (valptr - value), | |
523 | "%d", attr->values[i].boolean); | |
524 | break; | |
525 | ||
526 | case IPP_TAG_NOVALUE : | |
527 | strlcat(valptr, "novalue", sizeof(value) - (valptr - value)); | |
528 | break; | |
529 | ||
530 | case IPP_TAG_RANGE : | |
531 | snprintf(valptr, sizeof(value) - (valptr - value), | |
532 | "%d-%d", attr->values[i].range.lower, | |
533 | attr->values[i].range.upper); | |
534 | break; | |
535 | ||
536 | case IPP_TAG_RESOLUTION : | |
537 | snprintf(valptr, sizeof(value) - (valptr - value), | |
538 | "%dx%d%s", attr->values[i].resolution.xres, | |
539 | attr->values[i].resolution.yres, | |
540 | attr->values[i].resolution.units == IPP_RES_PER_INCH ? | |
541 | "dpi" : "dpc"); | |
542 | break; | |
543 | ||
544 | case IPP_TAG_URI : | |
545 | if (strchr(attr->values[i].string.text, ':') != NULL) | |
546 | { | |
547 | /* | |
548 | * Rewrite URIs... | |
549 | */ | |
550 | ||
551 | if (!strcmp(name, "member_uris")) | |
552 | { | |
553 | char url[1024]; /* URL for class member... */ | |
554 | ||
555 | ||
556 | cgiRewriteURL(attr->values[i].string.text, url, | |
557 | sizeof(url), NULL); | |
558 | ||
559 | snprintf(valptr, sizeof(value) - (valptr - value), | |
560 | "<A HREF=\"%s\">%s</A>", url, | |
561 | strrchr(url, '/') + 1); | |
562 | } | |
563 | else | |
564 | cgiRewriteURL(attr->values[i].string.text, valptr, | |
565 | sizeof(value) - (valptr - value), NULL); | |
566 | break; | |
567 | } | |
568 | ||
569 | case IPP_TAG_STRING : | |
570 | case IPP_TAG_TEXT : | |
571 | case IPP_TAG_NAME : | |
572 | case IPP_TAG_KEYWORD : | |
573 | case IPP_TAG_CHARSET : | |
574 | case IPP_TAG_LANGUAGE : | |
575 | case IPP_TAG_MIMETYPE : | |
576 | strlcat(valptr, attr->values[i].string.text, | |
577 | sizeof(value) - (valptr - value)); | |
578 | break; | |
579 | ||
580 | case IPP_TAG_BEGIN_COLLECTION : | |
581 | snprintf(value, sizeof(value), "%s%d", name, i + 1); | |
582 | cgiSetIPPVars(attr->values[i].collection, NULL, NULL, value, | |
583 | element); | |
584 | break; | |
585 | ||
586 | default : | |
587 | break; /* anti-compiler-warning-code */ | |
588 | } | |
589 | } | |
590 | ||
591 | /* | |
592 | * Add the element... | |
593 | */ | |
594 | ||
595 | if (attr->value_tag != IPP_TAG_BEGIN_COLLECTION) | |
596 | { | |
597 | cgiSetArray(name, element, value); | |
598 | ||
599 | fprintf(stderr, "DEBUG2: %s[%d]=\"%s\"\n", name, element, value); | |
600 | } | |
601 | } | |
602 | ||
603 | return (attr ? attr->next : NULL); | |
604 | } | |
605 | ||
606 | ||
607 | /* | |
608 | * 'cgiSetIPPVars()' - Set CGI variables from an IPP response. | |
609 | */ | |
610 | ||
611 | int /* O - Maximum number of elements */ | |
612 | cgiSetIPPVars(ipp_t *response, /* I - Response data to be copied... */ | |
613 | const char *filter_name, /* I - Filter name */ | |
614 | const char *filter_value, /* I - Filter value */ | |
615 | const char *prefix, /* I - Prefix for name or NULL */ | |
616 | int parent_el) /* I - Parent element number */ | |
617 | { | |
618 | int element; /* Element in CGI array */ | |
619 | ipp_attribute_t *attr, /* Attribute in response... */ | |
620 | *filter; /* Filtering attribute */ | |
621 | ||
622 | ||
623 | fprintf(stderr, "DEBUG2: cgiSetIPPVars(response=%p, filter_name=\"%s\", " | |
624 | "filter_value=\"%s\", prefix=\"%s\", parent_el=%d)\n", | |
625 | response, filter_name, filter_value, prefix, parent_el); | |
626 | ||
627 | /* | |
628 | * Set common CGI template variables... | |
629 | */ | |
630 | ||
631 | if (!prefix) | |
632 | cgiSetServerVersion(); | |
633 | ||
634 | /* | |
635 | * Loop through the attributes and set them for the template... | |
636 | */ | |
637 | ||
638 | attr = response->attrs; | |
639 | ||
640 | if (!prefix) | |
641 | while (attr && attr->group_tag == IPP_TAG_OPERATION) | |
642 | attr = attr->next; | |
643 | ||
644 | for (element = parent_el; attr; element ++) | |
645 | { | |
646 | /* | |
647 | * Copy attributes to a separator... | |
648 | */ | |
649 | ||
650 | while (attr && attr->group_tag == IPP_TAG_ZERO) | |
651 | attr= attr->next; | |
652 | ||
653 | if (!attr) | |
654 | break; | |
655 | ||
656 | if (filter_name) | |
657 | { | |
658 | for (filter = attr; | |
659 | filter != NULL && filter->group_tag != IPP_TAG_ZERO; | |
660 | filter = filter->next) | |
661 | if (filter->name && !strcmp(filter->name, filter_name) && | |
662 | (filter->value_tag == IPP_TAG_STRING || | |
663 | (filter->value_tag >= IPP_TAG_TEXTLANG && | |
664 | filter->value_tag <= IPP_TAG_MIMETYPE)) && | |
665 | filter->values[0].string.text != NULL && | |
666 | !strcasecmp(filter->values[0].string.text, filter_value)) | |
667 | break; | |
668 | ||
669 | if (!filter) | |
670 | return (element + 1); | |
671 | ||
672 | if (filter->group_tag == IPP_TAG_ZERO) | |
673 | { | |
674 | attr = filter; | |
675 | element --; | |
676 | continue; | |
677 | } | |
678 | } | |
679 | ||
680 | attr = cgiSetIPPObjectVars(attr, prefix, element); | |
681 | } | |
682 | ||
683 | fprintf(stderr, "DEBUG2: Returing %d from cgiSetIPPVars()...\n", element + 1); | |
684 | ||
685 | return (element + 1); | |
686 | } | |
687 | ||
688 | ||
689 | /* | |
690 | * 'cgiShowJobs()' - Show print jobs. | |
691 | */ | |
692 | ||
693 | void | |
694 | cgiShowJobs(http_t *http, /* I - Connection to server */ | |
695 | const char *dest) /* I - Destination name or NULL */ | |
696 | { | |
697 | int i; /* Looping var */ | |
698 | const char *which_jobs; /* Which jobs to show */ | |
699 | ipp_t *request, /* IPP request */ | |
700 | *response; /* IPP response */ | |
701 | cups_array_t *jobs; /* Array of job objects */ | |
702 | ipp_attribute_t *job; /* Job object */ | |
703 | int ascending, /* Order of jobs (0 = descending) */ | |
704 | first, /* First job to show */ | |
705 | count; /* Number of jobs */ | |
706 | const char *var; /* Form variable */ | |
707 | void *search; /* Search data */ | |
708 | char url[1024], /* URL for prev/next/this */ | |
709 | *urlptr, /* Position in URL */ | |
710 | *urlend; /* End of URL */ | |
711 | cups_lang_t *language; /* Language information */ | |
712 | ||
713 | ||
714 | /* | |
715 | * Build an IPP_GET_JOBS request, which requires the following | |
716 | * attributes: | |
717 | * | |
718 | * attributes-charset | |
719 | * attributes-natural-language | |
720 | * printer-uri | |
721 | */ | |
722 | ||
723 | request = ippNew(); | |
724 | ||
725 | language = cupsLangDefault(); | |
726 | ||
727 | ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET, | |
728 | "attributes-charset", NULL, cupsLangEncoding(language)); | |
729 | ||
730 | ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE, | |
731 | "attributes-natural-language", NULL, language->language); | |
732 | ||
733 | request->request.op.operation_id = IPP_GET_JOBS; | |
734 | request->request.op.request_id = 1; | |
735 | ||
736 | if (dest) | |
737 | { | |
738 | httpAssembleURIf(url, sizeof(url), "ipp", NULL, "localhost", ippPort(), | |
739 | "/printers/%s", dest); | |
740 | ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", | |
741 | NULL, url); | |
742 | } | |
743 | else | |
744 | ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri", NULL, | |
745 | "ipp://localhost/jobs"); | |
746 | ||
747 | if ((which_jobs = cgiGetVariable("which_jobs")) != NULL) | |
748 | ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, "which-jobs", | |
749 | NULL, which_jobs); | |
750 | ||
751 | cgiGetAttributes(request, "jobs.tmpl"); | |
752 | ||
753 | /* | |
754 | * Do the request and get back a response... | |
755 | */ | |
756 | ||
757 | if ((response = cupsDoRequest(http, request, "/")) != NULL) | |
758 | { | |
759 | /* | |
760 | * Get a list of matching job objects. | |
761 | */ | |
762 | ||
763 | if (!dest && (var = cgiGetVariable("QUERY")) != NULL) | |
764 | search = cgiCompileSearch(var); | |
765 | else | |
766 | search = NULL; | |
767 | ||
768 | jobs = cgiGetIPPObjects(response, search); | |
769 | count = cupsArrayCount(jobs); | |
770 | ||
771 | if (search) | |
772 | cgiFreeSearch(search); | |
773 | ||
774 | /* | |
775 | * Figure out which jobs to display... | |
776 | */ | |
777 | ||
778 | if ((var = cgiGetVariable("FIRST")) != NULL) | |
779 | first = atoi(var); | |
780 | else | |
781 | first = 0; | |
782 | ||
783 | if (first >= count) | |
784 | first = count - CUPS_PAGE_MAX; | |
785 | ||
786 | first = (first / CUPS_PAGE_MAX) * CUPS_PAGE_MAX; | |
787 | ||
788 | if (first < 0) | |
789 | first = 0; | |
790 | ||
791 | sprintf(url, "%d", count); | |
792 | cgiSetVariable("TOTAL", url); | |
793 | ||
794 | if ((var = cgiGetVariable("ORDER")) != NULL) | |
795 | ascending = !strcasecmp(var, "asc"); | |
796 | else | |
797 | ascending = 1; | |
798 | ||
799 | if (ascending) | |
800 | { | |
801 | for (i = 0, job = (ipp_attribute_t *)cupsArrayIndex(jobs, first); | |
802 | i < CUPS_PAGE_MAX && job; | |
803 | i ++, job = (ipp_attribute_t *)cupsArrayNext(jobs)) | |
804 | cgiSetIPPObjectVars(job, NULL, i); | |
805 | } | |
806 | else | |
807 | { | |
808 | for (i = 0, job = (ipp_attribute_t *)cupsArrayIndex(jobs, count - first - 1); | |
809 | i < CUPS_PAGE_MAX && job; | |
810 | i ++, job = (ipp_attribute_t *)cupsArrayPrev(jobs)) | |
811 | cgiSetIPPObjectVars(job, NULL, i); | |
812 | } | |
813 | ||
814 | /* | |
815 | * Save navigation URLs... | |
816 | */ | |
817 | ||
818 | urlend = url + sizeof(url); | |
819 | ||
820 | if (dest) | |
821 | { | |
822 | snprintf(url, sizeof(url), "/%s/%s?", cgiGetVariable("SECTION"), dest); | |
823 | urlptr = url + strlen(url); | |
824 | } | |
825 | else if ((var = cgiGetVariable("QUERY")) != NULL) | |
826 | { | |
827 | strlcpy(url, "/jobs/?QUERY=", sizeof(url)); | |
828 | urlptr = url + strlen(url); | |
829 | ||
830 | cgiFormEncode(urlptr, var, urlend - urlptr); | |
831 | urlptr += strlen(urlptr); | |
832 | ||
833 | strlcpy(urlptr, "&", urlend - urlptr); | |
834 | urlptr += strlen(urlptr); | |
835 | } | |
836 | else | |
837 | { | |
838 | strlcpy(url, "/jobs/?", sizeof(url)); | |
839 | urlptr = url + strlen(url); | |
840 | } | |
841 | ||
842 | if (which_jobs) | |
843 | { | |
844 | strlcpy(urlptr, "WHICH_JOBS=", urlend - urlptr); | |
845 | urlptr += strlen(urlptr); | |
846 | ||
847 | cgiFormEncode(urlptr, which_jobs, urlend - urlptr); | |
848 | urlptr += strlen(urlptr); | |
849 | ||
850 | strlcpy(urlptr, "&", urlend - urlptr); | |
851 | urlptr += strlen(urlptr); | |
852 | } | |
853 | ||
854 | snprintf(urlptr, urlend - urlptr, "FIRST=%d", first); | |
855 | cgiSetVariable("THISURL", url); | |
856 | ||
857 | if (first > 0) | |
858 | { | |
859 | snprintf(urlptr, urlend - urlptr, "FIRST=%d&ORDER=%s", | |
860 | first - CUPS_PAGE_MAX, ascending ? "asc" : "dec"); | |
861 | cgiSetVariable("PREVURL", url); | |
862 | } | |
863 | ||
864 | if ((first + CUPS_PAGE_MAX) < count) | |
865 | { | |
866 | snprintf(urlptr, urlend - urlptr, "FIRST=%d&ORDER=%s", | |
867 | first + CUPS_PAGE_MAX, ascending ? "asc" : "dec"); | |
868 | cgiSetVariable("NEXTURL", url); | |
869 | } | |
870 | ||
871 | /* | |
872 | * Then show everything... | |
873 | */ | |
874 | ||
875 | if (!dest) | |
876 | cgiCopyTemplateLang("search.tmpl"); | |
877 | ||
878 | cgiCopyTemplateLang("jobs-header.tmpl"); | |
879 | ||
880 | if (count > CUPS_PAGE_MAX) | |
881 | cgiCopyTemplateLang("page.tmpl"); | |
882 | ||
883 | cgiCopyTemplateLang("jobs.tmpl"); | |
884 | ||
885 | if (count > CUPS_PAGE_MAX) | |
886 | cgiCopyTemplateLang("page.tmpl"); | |
887 | ||
888 | ippDelete(response); | |
889 | } | |
890 | } | |
891 | ||
892 | ||
893 | ||
894 | /* | |
895 | * End of "$Id: ipp-var.c 4921 2006-01-12 21:26:26Z mike $". | |
896 | */ |