]> git.ipfire.org Git - thirdparty/cups.git/blob - cgi-bin/ipp-var.c
Load cups into easysw/current.
[thirdparty/cups.git] / cgi-bin / ipp-var.c
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 */