]>
git.ipfire.org Git - thirdparty/cups.git/blob - cgi-bin/ipp-var.c
2 * "$Id: ipp-var.c 4921 2006-01-12 21:26:26Z mike $"
4 * CGI <-> IPP variable routines for the Common UNIX Printing System (CUPS).
6 * Copyright 1997-2006 by Easy Software Products.
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
15 * Attn: CUPS Licensing Information
16 * Easy Software Products
17 * 44141 Airport View Drive, Suite 204
18 * Hollywood, Maryland 20636 USA
20 * Voice: (301) 373-9600
21 * EMail: cups-info@cups.org
22 * WWW: http://www.cups.org
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.
35 * Include necessary headers...
38 #include "cgi-private.h"
42 * 'cgiGetAttributes()' - Get the list of attributes that are needed
43 * by the template file.
47 cgiGetAttributes(ipp_t
*request
, /* I - IPP request */
48 const char *tmpl
) /* I - Base filename */
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 */
57 FILE *in
; /* Input file */
58 int ch
; /* Character from file */
59 char name
[255], /* Name of variable */
60 *nameptr
; /* Pointer into name */
64 * Convert the language to a locale name...
67 if ((lang
= getenv("LANG")) != NULL
)
69 for (i
= 0; lang
[i
] && i
< 15; i
++)
70 if (isalnum(lang
[i
] & 255))
71 locale
[i
] = tolower(lang
[i
]);
81 * See if we have a template file for this language...
84 directory
= cgiGetTemplateDir();
86 snprintf(filename
, sizeof(filename
), "%s/%s/%s", directory
, locale
, tmpl
);
87 if (access(filename
, 0))
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
);
97 * Open the template file...
100 if ((in
= fopen(filename
, "r")) == NULL
)
104 * Loop through the file adding attribute names as needed...
109 while ((ch
= getc(in
)) != EOF
)
112 else if (ch
== '{' && num_attrs
< (sizeof(attrs
) / sizeof(attrs
[0])))
118 for (nameptr
= name
; (ch
= getc(in
)) != EOF
;)
119 if (strchr("}]<>=! \t\n", ch
))
121 else if (nameptr
> name
&& ch
== '?')
123 else if (nameptr
< (name
+ sizeof(name
) - 1))
133 if (!strncmp(name
, "printer_state_history", 21))
134 strcpy(name
, "printer_state_history");
137 * Possibly add it to the list of attributes...
140 for (i
= 0; i
< num_attrs
; i
++)
141 if (!strcmp(attrs
[i
], name
))
146 attrs
[num_attrs
] = strdup(name
);
152 * If we have attributes, add a requested-attributes attribute to the
158 ippAddStrings(request
, IPP_TAG_OPERATION
, IPP_TAG_KEYWORD
,
159 "requested-attributes", num_attrs
, NULL
, (const char **)attrs
);
161 for (i
= 0; i
< num_attrs
; i
++)
168 * 'cupsGetIPPObjects()' - Get the objects in an IPP response.
171 cups_array_t
* /* O - Array of objects */
172 cgiGetIPPObjects(ipp_t
*response
, /* I - IPP response */
173 void *search
) /* I - Search filter */
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? */
186 for (add
= 0, first
= NULL
, objs
= cupsArrayNew(NULL
, NULL
),
187 group
= IPP_TAG_ZERO
, attr
= response
->attrs
;
191 if (attr
->group_tag
!= group
)
193 group
= attr
->group_tag
;
195 if (group
!= IPP_TAG_ZERO
&& group
!= IPP_TAG_OPERATION
)
200 else if (add
&& first
)
202 cupsArrayAdd(objs
, first
);
209 if (attr
->name
&& attr
->group_tag
!= IPP_TAG_OPERATION
&& !add
)
214 * Add all objects if there is no search...
222 * Check the search string against the string and integer values.
225 switch (attr
->value_tag
)
227 case IPP_TAG_TEXTLANG
:
228 case IPP_TAG_NAMELANG
:
231 case IPP_TAG_KEYWORD
:
233 case IPP_TAG_MIMETYPE
:
234 for (i
= 0; !add
&& i
< attr
->num_values
; i
++)
235 if (cgiDoSearch(search
, attr
->values
[i
].string
.text
))
239 case IPP_TAG_INTEGER
:
240 for (i
= 0; !add
&& i
< attr
->num_values
; i
++)
242 char buf
[255]; /* Number buffer */
245 sprintf(buf
, "%d", attr
->values
[i
].integer
);
247 if (cgiDoSearch(search
, buf
))
260 cupsArrayAdd(objs
, first
);
267 * 'cgiRewriteURL()' - Rewrite a printer URI into a web browser URL...
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 */
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 */
294 * Check if we have been called before...
300 * No, initialize static vars for the conversion...
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...
307 if ((server
= getenv("SERVER_NAME")) == NULL
)
310 httpGetHostname(servername
, sizeof(servername
));
313 * Then flag whether we are using SSL on this connection...
316 ishttps
= getenv("HTTPS") != NULL
;
320 * Convert the URI to a URL...
323 httpSeparateURI(uri
, method
, sizeof(method
), userpass
, sizeof(userpass
),
324 hostname
, sizeof(hostname
), &port
,
325 rawresource
, sizeof(rawresource
));
327 if (!strcmp(method
, "ipp") ||
328 !strcmp(method
, "http") ||
329 !strcmp(method
, "https"))
334 * Force the specified resource name instead of the one in the URL...
337 strlcpy(resource
, newresource
, sizeof(resource
));
342 * Rewrite the resource string so it doesn't contain any
346 for (rawptr
= rawresource
, resptr
= resource
; *rawptr
; rawptr
++)
347 if ((*rawptr
& 128) || *rawptr
== '%' || *rawptr
== ' ' ||
348 *rawptr
== '#' || *rawptr
== '?' ||
349 *rawptr
== '.') /* For MSIE */
351 if (resptr
< (resource
+ sizeof(resource
) - 3))
354 *resptr
++ = hexchars
[(*rawptr
>> 4) & 15];
355 *resptr
++ = hexchars
[*rawptr
& 15];
358 else if (resptr
< (resource
+ sizeof(resource
) - 1))
365 * Map local access to a local URI...
368 if (!strcasecmp(hostname
, "localhost") ||
369 !strncasecmp(hostname
, "localhost.", 10) ||
370 !strcasecmp(hostname
, server
) ||
371 !strcasecmp(hostname
, servername
))
374 * Make URI relative to the current server...
377 strlcpy(url
, resource
, urlsize
);
382 * Rewrite URI with HTTP/HTTPS scheme...
386 snprintf(url
, urlsize
, "%s://%s@%s:%d%s",
387 ishttps
? "https" : "http",
388 userpass
, hostname
, port
, resource
);
390 snprintf(url
, urlsize
, "%s://%s:%d%s",
391 ishttps
? "https" : "http",
392 hostname
, port
, resource
);
396 strlcpy(url
, uri
, urlsize
);
403 * 'cgiSetIPPObjectVars()' - Set CGI variables from an IPP object.
406 ipp_attribute_t
* /* O - Next object */
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 */
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 */
421 fprintf(stderr
, "DEBUG2: cgiSetIPPObjectVars(obj=%p, prefix=\"%s\", "
423 obj
, prefix
, element
);
426 * Set common CGI template variables...
430 cgiSetServerVersion();
433 * Loop through the attributes and set them for the template...
436 for (attr
= obj
; attr
&& attr
->group_tag
!= IPP_TAG_ZERO
; attr
= attr
->next
)
439 * Copy the attribute name, substituting "_" for "-"...
447 snprintf(name
, sizeof(name
), "%s.", prefix
);
448 nameptr
= name
+ strlen(name
);
453 for (i
= 0; attr
->name
[i
] && nameptr
< (name
+ sizeof(name
) - 1); i
++)
454 if (attr
->name
[i
] == '-')
457 *nameptr
++ = attr
->name
[i
];
462 * Add "job_printer_name" variable if we have a "job_printer_uri"
466 if (!strcmp(name
, "job_printer_uri"))
468 if ((valptr
= strrchr(attr
->values
[0].string
.text
, '/')) == NULL
)
473 cgiSetArray("job_printer_name", element
, valptr
);
477 * Add "admin_uri" variable if we have a "printer_uri_supported"
481 if (!strcmp(name
, "printer_uri_supported"))
483 cgiRewriteURL(attr
->values
[0].string
.text
, value
, sizeof(value
),
486 cgiSetArray("admin_uri", element
, value
);
493 value
[0] = '\0'; /* Initially an empty string */
494 valptr
= value
; /* Start at the beginning */
496 for (i
= 0; i
< attr
->num_values
; i
++)
499 strlcat(valptr
, ",", sizeof(value
) - (valptr
- value
));
501 valptr
+= strlen(valptr
);
503 switch (attr
->value_tag
)
505 case IPP_TAG_INTEGER
:
507 if (strncmp(name
, "time_at_", 8) == 0)
509 time_t t
; /* Temporary time value */
511 t
= (time_t)attr
->values
[i
].integer
;
512 date
= localtime(&t
);
514 strftime(valptr
, sizeof(value
) - (valptr
- value
), "%c", date
);
517 snprintf(valptr
, sizeof(value
) - (valptr
- value
),
518 "%d", attr
->values
[i
].integer
);
521 case IPP_TAG_BOOLEAN
:
522 snprintf(valptr
, sizeof(value
) - (valptr
- value
),
523 "%d", attr
->values
[i
].boolean
);
526 case IPP_TAG_NOVALUE
:
527 strlcat(valptr
, "novalue", sizeof(value
) - (valptr
- value
));
531 snprintf(valptr
, sizeof(value
) - (valptr
- value
),
532 "%d-%d", attr
->values
[i
].range
.lower
,
533 attr
->values
[i
].range
.upper
);
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
?
545 if (strchr(attr
->values
[i
].string
.text
, ':') != NULL
)
551 if (!strcmp(name
, "member_uris"))
553 char url
[1024]; /* URL for class member... */
556 cgiRewriteURL(attr
->values
[i
].string
.text
, url
,
559 snprintf(valptr
, sizeof(value
) - (valptr
- value
),
560 "<A HREF=\"%s\">%s</A>", url
,
561 strrchr(url
, '/') + 1);
564 cgiRewriteURL(attr
->values
[i
].string
.text
, valptr
,
565 sizeof(value
) - (valptr
- value
), NULL
);
569 case IPP_TAG_STRING
:
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
));
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
,
587 break; /* anti-compiler-warning-code */
595 if (attr
->value_tag
!= IPP_TAG_BEGIN_COLLECTION
)
597 cgiSetArray(name
, element
, value
);
599 fprintf(stderr
, "DEBUG2: %s[%d]=\"%s\"\n", name
, element
, value
);
603 return (attr
? attr
->next
: NULL
);
608 * 'cgiSetIPPVars()' - Set CGI variables from an IPP response.
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 */
618 int element
; /* Element in CGI array */
619 ipp_attribute_t
*attr
, /* Attribute in response... */
620 *filter
; /* Filtering attribute */
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
);
628 * Set common CGI template variables...
632 cgiSetServerVersion();
635 * Loop through the attributes and set them for the template...
638 attr
= response
->attrs
;
641 while (attr
&& attr
->group_tag
== IPP_TAG_OPERATION
)
644 for (element
= parent_el
; attr
; element
++)
647 * Copy attributes to a separator...
650 while (attr
&& attr
->group_tag
== IPP_TAG_ZERO
)
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
))
670 return (element
+ 1);
672 if (filter
->group_tag
== IPP_TAG_ZERO
)
680 attr
= cgiSetIPPObjectVars(attr
, prefix
, element
);
683 fprintf(stderr
, "DEBUG2: Returing %d from cgiSetIPPVars()...\n", element
+ 1);
685 return (element
+ 1);
690 * 'cgiShowJobs()' - Show print jobs.
694 cgiShowJobs(http_t
*http
, /* I - Connection to server */
695 const char *dest
) /* I - Destination name or NULL */
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 */
715 * Build an IPP_GET_JOBS request, which requires the following
719 * attributes-natural-language
725 language
= cupsLangDefault();
727 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_CHARSET
,
728 "attributes-charset", NULL
, cupsLangEncoding(language
));
730 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_LANGUAGE
,
731 "attributes-natural-language", NULL
, language
->language
);
733 request
->request
.op
.operation_id
= IPP_GET_JOBS
;
734 request
->request
.op
.request_id
= 1;
738 httpAssembleURIf(url
, sizeof(url
), "ipp", NULL
, "localhost", ippPort(),
739 "/printers/%s", dest
);
740 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
, "printer-uri",
744 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
, "job-uri", NULL
,
745 "ipp://localhost/jobs");
747 if ((which_jobs
= cgiGetVariable("which_jobs")) != NULL
)
748 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_KEYWORD
, "which-jobs",
751 cgiGetAttributes(request
, "jobs.tmpl");
754 * Do the request and get back a response...
757 if ((response
= cupsDoRequest(http
, request
, "/")) != NULL
)
760 * Get a list of matching job objects.
763 if (!dest
&& (var
= cgiGetVariable("QUERY")) != NULL
)
764 search
= cgiCompileSearch(var
);
768 jobs
= cgiGetIPPObjects(response
, search
);
769 count
= cupsArrayCount(jobs
);
772 cgiFreeSearch(search
);
775 * Figure out which jobs to display...
778 if ((var
= cgiGetVariable("FIRST")) != NULL
)
784 first
= count
- CUPS_PAGE_MAX
;
786 first
= (first
/ CUPS_PAGE_MAX
) * CUPS_PAGE_MAX
;
791 sprintf(url
, "%d", count
);
792 cgiSetVariable("TOTAL", url
);
794 if ((var
= cgiGetVariable("ORDER")) != NULL
)
795 ascending
= !strcasecmp(var
, "asc");
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
);
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
);
815 * Save navigation URLs...
818 urlend
= url
+ sizeof(url
);
822 snprintf(url
, sizeof(url
), "/%s/%s?", cgiGetVariable("SECTION"), dest
);
823 urlptr
= url
+ strlen(url
);
825 else if ((var
= cgiGetVariable("QUERY")) != NULL
)
827 strlcpy(url
, "/jobs/?QUERY=", sizeof(url
));
828 urlptr
= url
+ strlen(url
);
830 cgiFormEncode(urlptr
, var
, urlend
- urlptr
);
831 urlptr
+= strlen(urlptr
);
833 strlcpy(urlptr
, "&", urlend
- urlptr
);
834 urlptr
+= strlen(urlptr
);
838 strlcpy(url
, "/jobs/?", sizeof(url
));
839 urlptr
= url
+ strlen(url
);
844 strlcpy(urlptr
, "WHICH_JOBS=", urlend
- urlptr
);
845 urlptr
+= strlen(urlptr
);
847 cgiFormEncode(urlptr
, which_jobs
, urlend
- urlptr
);
848 urlptr
+= strlen(urlptr
);
850 strlcpy(urlptr
, "&", urlend
- urlptr
);
851 urlptr
+= strlen(urlptr
);
854 snprintf(urlptr
, urlend
- urlptr
, "FIRST=%d", first
);
855 cgiSetVariable("THISURL", url
);
859 snprintf(urlptr
, urlend
- urlptr
, "FIRST=%d&ORDER=%s",
860 first
- CUPS_PAGE_MAX
, ascending
? "asc" : "dec");
861 cgiSetVariable("PREVURL", url
);
864 if ((first
+ CUPS_PAGE_MAX
) < count
)
866 snprintf(urlptr
, urlend
- urlptr
, "FIRST=%d&ORDER=%s",
867 first
+ CUPS_PAGE_MAX
, ascending
? "asc" : "dec");
868 cgiSetVariable("NEXTURL", url
);
872 * Then show everything...
876 cgiCopyTemplateLang("search.tmpl");
878 cgiCopyTemplateLang("jobs-header.tmpl");
880 if (count
> CUPS_PAGE_MAX
)
881 cgiCopyTemplateLang("page.tmpl");
883 cgiCopyTemplateLang("jobs.tmpl");
885 if (count
> CUPS_PAGE_MAX
)
886 cgiCopyTemplateLang("page.tmpl");
895 * End of "$Id: ipp-var.c 4921 2006-01-12 21:26:26Z mike $".