]>
git.ipfire.org Git - thirdparty/cups.git/blob - cgi-bin/ipp-var.c
2 * "$Id: ipp-var.c 6304 2007-02-22 22:06:23Z mike $"
4 * CGI <-> IPP variable routines for the Common UNIX Printing System (CUPS).
6 * Copyright 1997-2007 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 * cgiGetIPPObjects() - Get the objects in an IPP response.
29 * cgiMoveJobs() - Move one or more jobs.
30 * cgiPrintTestPage() - Print a test page.
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.
34 * cgiShowIPPError() - Show the last IPP error message.
35 * cgiShowJobs() - Show print jobs.
36 * cgiText() - Return localized text.
40 * Include necessary headers...
43 #include "cgi-private.h"
47 * 'cgiGetAttributes()' - Get the list of attributes that are needed
48 * by the template file.
52 cgiGetAttributes(ipp_t
*request
, /* I - IPP request */
53 const char *tmpl
) /* I - Base filename */
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 */
62 FILE *in
; /* Input file */
63 int ch
; /* Character from file */
64 char name
[255], /* Name of variable */
65 *nameptr
; /* Pointer into name */
69 * Convert the language to a locale name...
72 if ((lang
= getenv("LANG")) != NULL
)
74 for (i
= 0; lang
[i
] && i
< 15; i
++)
75 if (isalnum(lang
[i
] & 255))
76 locale
[i
] = tolower(lang
[i
]);
86 * See if we have a template file for this language...
89 directory
= cgiGetTemplateDir();
91 snprintf(filename
, sizeof(filename
), "%s/%s/%s", directory
, locale
, tmpl
);
92 if (access(filename
, 0))
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
);
102 * Open the template file...
105 if ((in
= fopen(filename
, "r")) == NULL
)
109 * Loop through the file adding attribute names as needed...
113 attrs
[0] = NULL
; /* Eliminate compiler warning */
115 while ((ch
= getc(in
)) != EOF
)
118 else if (ch
== '{' && num_attrs
< (sizeof(attrs
) / sizeof(attrs
[0])))
124 for (nameptr
= name
; (ch
= getc(in
)) != EOF
;)
125 if (strchr("}]<>=! \t\n", ch
))
127 else if (nameptr
> name
&& ch
== '?')
129 else if (nameptr
< (name
+ sizeof(name
) - 1))
139 if (!strncmp(name
, "printer_state_history", 21))
140 strcpy(name
, "printer_state_history");
143 * Possibly add it to the list of attributes...
146 for (i
= 0; i
< num_attrs
; i
++)
147 if (!strcmp(attrs
[i
], name
))
152 attrs
[num_attrs
] = strdup(name
);
158 * If we have attributes, add a requested-attributes attribute to the
164 ippAddStrings(request
, IPP_TAG_OPERATION
, IPP_TAG_KEYWORD
,
165 "requested-attributes", num_attrs
, NULL
, (const char **)attrs
);
167 for (i
= 0; i
< num_attrs
; i
++)
174 * 'cgiGetIPPObjects()' - Get the objects in an IPP response.
177 cups_array_t
* /* O - Array of objects */
178 cgiGetIPPObjects(ipp_t
*response
, /* I - IPP response */
179 void *search
) /* I - Search filter */
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? */
192 for (add
= 0, first
= NULL
, objs
= cupsArrayNew(NULL
, NULL
),
193 group
= IPP_TAG_ZERO
, attr
= response
->attrs
;
197 if (attr
->group_tag
!= group
)
199 group
= attr
->group_tag
;
201 if (group
!= IPP_TAG_ZERO
&& group
!= IPP_TAG_OPERATION
)
206 else if (add
&& first
)
208 cupsArrayAdd(objs
, first
);
215 if (attr
->name
&& attr
->group_tag
!= IPP_TAG_OPERATION
&& !add
)
220 * Add all objects if there is no search...
228 * Check the search string against the string and integer values.
231 switch (attr
->value_tag
)
233 case IPP_TAG_TEXTLANG
:
234 case IPP_TAG_NAMELANG
:
237 case IPP_TAG_KEYWORD
:
239 case IPP_TAG_MIMETYPE
:
240 for (i
= 0; !add
&& i
< attr
->num_values
; i
++)
241 if (cgiDoSearch(search
, attr
->values
[i
].string
.text
))
245 case IPP_TAG_INTEGER
:
246 for (i
= 0; !add
&& i
< attr
->num_values
; i
++)
248 char buf
[255]; /* Number buffer */
251 sprintf(buf
, "%d", attr
->values
[i
].integer
);
253 if (cgiDoSearch(search
, buf
))
266 cupsArrayAdd(objs
, first
);
273 * 'cgiMoveJobs()' - Move one or more jobs.
275 * At least one of dest or job_id must be non-zero/NULL.
279 cgiMoveJobs(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 */
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 */
294 * See who is logged in...
297 if ((user
= getenv("REMOTE_USER")) == NULL
)
301 * See if the user has already selected a new destination...
304 if ((job_printer_uri
= cgiGetVariable("JOB_PRINTER_URI")) == NULL
)
307 * Make sure necessary form variables are set...
312 char temp
[255]; /* Temporary string */
315 sprintf(temp
, "%d", job_id
);
316 cgiSetVariable("JOB_ID", temp
);
320 cgiSetVariable("PRINTER_NAME", dest
);
323 * No new destination specified, show the user what the available
324 * printers/classes are...
330 * Get the current destination for job N...
333 char job_uri
[1024]; /* Job URI */
336 request
= ippNewRequest(IPP_GET_JOB_ATTRIBUTES
);
338 snprintf(job_uri
, sizeof(job_uri
), "ipp://localhost/jobs/%d", job_id
);
339 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
, "job-uri",
341 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_KEYWORD
,
342 "requested-attributes", NULL
, "job-printer-uri");
344 if ((response
= cupsDoRequest(http
, request
, "/")) != NULL
)
346 if ((attr
= ippFindAttribute(response
, "job-printer-uri",
347 IPP_TAG_URI
)) != NULL
)
350 * Pull the name from the URI...
353 strlcpy(current_dest
, strrchr(attr
->values
[0].string
.text
, '/') + 1,
354 sizeof(current_dest
));
364 * Couldn't get the current destination...
367 cgiStartHTML(cgiText(_("Move Job")));
368 cgiShowIPPError(_("Unable to find destination for job!"));
375 * Get the list of available destinations...
378 request
= ippNewRequest(CUPS_GET_PRINTERS
);
380 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_KEYWORD
,
381 "requested-attributes", NULL
, "printer-uri-supported");
383 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_NAME
,
384 "requesting-user-name", NULL
, user
);
386 if ((response
= cupsDoRequest(http
, request
, "/")) != NULL
)
388 for (i
= 0, attr
= ippFindAttribute(response
, "printer-uri-supported",
391 attr
= ippFindNextAttribute(response
, "printer-uri-supported",
395 * Pull the name from the URI...
398 name
= strrchr(attr
->values
[0].string
.text
, '/') + 1;
401 * If the name is not the same as the current destination, add it!
404 if (strcasecmp(name
, dest
))
406 cgiSetArray("JOB_PRINTER_URI", i
, attr
->values
[0].string
.text
);
407 cgiSetArray("JOB_PRINTER_NAME", i
, name
);
420 cgiStartHTML(cgiText(_("Move Job")));
422 cgiStartHTML(cgiText(_("Move All Jobs")));
424 cgiCopyTemplateLang("job-move.tmpl");
429 * Try moving the job or jobs...
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 */
438 request
= ippNewRequest(CUPS_MOVE_JOB
);
446 snprintf(resource
, sizeof(resource
), "/jobs/%d", job_id
);
448 snprintf(uri
, sizeof(uri
), "ipp://localhost/jobs/%d", job_id
);
449 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
, "job-uri",
455 * Move all active jobs on a destination...
458 snprintf(resource
, sizeof(resource
), "/%s/%s",
459 cgiGetVariable("SECTION"), dest
);
461 httpAssembleURIf(HTTP_URI_CODING_ALL
, uri
, sizeof(uri
), "ipp", NULL
,
462 "localhost", ippPort(), "/%s/%s",
463 cgiGetVariable("SECTION"), dest
);
464 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
, "printer-uri",
468 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
, "job-printer-uri",
469 NULL
, job_printer_uri
);
471 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_NAME
,
472 "requesting-user-name", NULL
, user
);
474 ippDelete(cupsDoRequest(http
, request
, resource
));
477 * Show the results...
480 job_printer_name
= strrchr(job_printer_uri
, '/') + 1;
482 if (cupsLastError() <= IPP_OK_CONFLICT
)
484 cgiRewriteURL(job_printer_uri
, resource
, sizeof(resource
), NULL
);
485 cgiFormEncode(uri
, resource
, sizeof(uri
));
486 snprintf(refresh
, sizeof(refresh
), "2;URL=%s", uri
);
487 cgiSetVariable("refresh_page", refresh
);
491 cgiStartHTML(cgiText(_("Move Job")));
493 cgiStartHTML(cgiText(_("Move All Jobs")));
495 if (cupsLastError() > IPP_OK_CONFLICT
)
498 cgiShowIPPError(_("Unable to move job"));
500 cgiShowIPPError(_("Unable to move jobs"));
504 cgiSetVariable("JOB_PRINTER_NAME", job_printer_name
);
505 cgiCopyTemplateLang("job-moved.tmpl");
514 * 'cgiPrintTestPage()' - Print a test page.
518 cgiPrintTestPage(http_t
*http
, /* I - Connection to server */
519 const char *dest
) /* I - Destination printer/class */
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 */
532 * See who is logged in...
535 if ((user
= getenv("REMOTE_USER")) == NULL
)
539 * Locate the test page file...
542 if ((datadir
= getenv("CUPS_DATADIR")) == NULL
)
543 datadir
= CUPS_DATADIR
;
545 snprintf(filename
, sizeof(filename
), "%s/data/testprint.ps", datadir
);
548 * Point to the printer/class...
551 snprintf(resource
, sizeof(resource
), "/%s/%s", cgiGetVariable("SECTION"),
554 httpAssembleURIf(HTTP_URI_CODING_ALL
, uri
, sizeof(uri
), "ipp", NULL
,
555 "localhost", ippPort(), "/%s/%s", cgiGetVariable("SECTION"),
559 * Build an IPP_PRINT_JOB request, which requires the following
563 * attributes-natural-language
565 * requesting-user-name
569 request
= ippNewRequest(IPP_PRINT_JOB
);
571 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
, "printer-uri",
574 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_NAME
,
575 "requesting-user-name", NULL
, user
);
577 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_NAME
, "job-name",
580 ippAddString(request
, IPP_TAG_JOB
, IPP_TAG_MIMETYPE
, "document-format",
581 NULL
, "application/postscript");
584 * Do the request and get back a response...
587 if ((response
= cupsDoFileRequest(http
, request
, resource
,
590 cgiSetIPPVars(response
, NULL
, NULL
, NULL
, 0);
595 if (cupsLastError() <= IPP_OK_CONFLICT
)
598 * Automatically reload the printer status page...
601 cgiFormEncode(uri
, resource
, sizeof(uri
));
602 snprintf(refresh
, sizeof(refresh
), "2;URL=%s", uri
);
603 cgiSetVariable("refresh_page", refresh
);
606 cgiStartHTML(cgiText(_("Print Test Page")));
608 if (cupsLastError() > IPP_OK_CONFLICT
)
609 cgiShowIPPError(_("Unable to print test page:"));
612 cgiSetVariable("PRINTER_NAME", dest
);
614 cgiCopyTemplateLang("test-page.tmpl");
622 * 'cgiRewriteURL()' - Rewrite a printer URI into a web browser URL...
625 char * /* O - New URL */
626 cgiRewriteURL(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 */
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 */
649 * Check if we have been called before...
655 * No, initialize static vars for the conversion...
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...
662 if ((server
= getenv("SERVER_NAME")) == NULL
)
665 httpGetHostname(NULL
, servername
, sizeof(servername
));
668 * Then flag whether we are using SSL on this connection...
671 ishttps
= getenv("HTTPS") != NULL
;
675 * Convert the URI to a URL...
678 httpSeparateURI(HTTP_URI_CODING_ALL
, uri
, method
, sizeof(method
), userpass
,
679 sizeof(userpass
), hostname
, sizeof(hostname
), &port
,
680 rawresource
, sizeof(rawresource
));
682 if (!strcmp(method
, "ipp") ||
683 !strcmp(method
, "http") ||
684 !strcmp(method
, "https"))
689 * Force the specified resource name instead of the one in the URL...
692 strlcpy(resource
, newresource
, sizeof(resource
));
697 * Rewrite the resource string so it doesn't contain any
701 for (rawptr
= rawresource
, resptr
= resource
; *rawptr
; rawptr
++)
702 if ((*rawptr
& 128) || *rawptr
== '%' || *rawptr
== ' ' ||
703 *rawptr
== '#' || *rawptr
== '?' ||
704 *rawptr
== '.') /* For MSIE */
706 if (resptr
< (resource
+ sizeof(resource
) - 3))
709 *resptr
++ = hexchars
[(*rawptr
>> 4) & 15];
710 *resptr
++ = hexchars
[*rawptr
& 15];
713 else if (resptr
< (resource
+ sizeof(resource
) - 1))
720 * Map local access to a local URI...
723 if (!strcasecmp(hostname
, "localhost") ||
724 !strncasecmp(hostname
, "localhost.", 10) ||
725 !strcasecmp(hostname
, server
) ||
726 !strcasecmp(hostname
, servername
))
729 * Make URI relative to the current server...
732 strlcpy(url
, resource
, urlsize
);
737 * Rewrite URI with HTTP/HTTPS scheme...
741 snprintf(url
, urlsize
, "%s://%s@%s:%d%s",
742 ishttps
? "https" : "http",
743 userpass
, hostname
, port
, resource
);
745 snprintf(url
, urlsize
, "%s://%s:%d%s",
746 ishttps
? "https" : "http",
747 hostname
, port
, resource
);
751 strlcpy(url
, uri
, urlsize
);
758 * 'cgiSetIPPObjectVars()' - Set CGI variables from an IPP object.
761 ipp_attribute_t
* /* O - Next object */
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 */
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 */
776 fprintf(stderr
, "DEBUG2: cgiSetIPPObjectVars(obj=%p, prefix=\"%s\", "
778 obj
, prefix
? prefix
: "(null)", element
);
781 * Set common CGI template variables...
785 cgiSetServerVersion();
788 * Loop through the attributes and set them for the template...
791 for (attr
= obj
; attr
&& attr
->group_tag
!= IPP_TAG_ZERO
; attr
= attr
->next
)
794 * Copy the attribute name, substituting "_" for "-"...
802 snprintf(name
, sizeof(name
), "%s.", prefix
);
803 nameptr
= name
+ strlen(name
);
808 for (i
= 0; attr
->name
[i
] && nameptr
< (name
+ sizeof(name
) - 1); i
++)
809 if (attr
->name
[i
] == '-')
812 *nameptr
++ = attr
->name
[i
];
817 * Add "job_printer_name" variable if we have a "job_printer_uri"
821 if (!strcmp(name
, "job_printer_uri"))
823 if ((valptr
= strrchr(attr
->values
[0].string
.text
, '/')) == NULL
)
828 cgiSetArray("job_printer_name", element
, valptr
);
832 * Localize event names in "notify_events" variable...
835 if (!strcmp(name
, "notify_events"))
837 size_t remaining
; /* Remaining bytes in buffer */
843 for (i
= 0; i
< attr
->num_values
; i
++)
845 if (valptr
>= (value
+ sizeof(value
) - 3))
854 remaining
= sizeof(value
) - (valptr
- value
);
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
);
881 strlcpy(valptr
, attr
->values
[i
].string
.text
, remaining
);
883 valptr
+= strlen(valptr
);
886 cgiSetArray("notify_events", element
, value
);
891 * Add "notify_printer_name" variable if we have a "notify_printer_uri"
895 if (!strcmp(name
, "notify_printer_uri"))
897 if ((valptr
= strrchr(attr
->values
[0].string
.text
, '/')) == NULL
)
902 cgiSetArray("notify_printer_name", element
, valptr
);
906 * Add "notify_recipient_name" variable if we have a "notify_recipient_uri"
907 * attribute, and rewrite recipient URI...
910 if (!strcmp(name
, "notify_recipient_uri"))
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 */
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
));
925 if (!strcmp(scheme
, "rss"))
928 * RSS notification...
931 if ((options
= strchr(resource
, '?')) != NULL
)
937 * Link to remote feed...
940 httpAssembleURI(HTTP_URI_CODING_ALL
, uri
, sizeof(uri
), "http",
941 userpass
, host
, port
, resource
);
942 strlcpy(name
, uri
, sizeof(name
));
947 * Link to local feed...
950 snprintf(uri
, sizeof(uri
), "/rss%s", resource
);
951 strlcpy(name
, resource
+ 1, sizeof(name
));
960 strlcpy(uri
, attr
->values
[0].string
.text
, sizeof(uri
));
961 strlcpy(name
, resource
, sizeof(name
));
964 cgiSetArray("notify_recipient_uri", element
, uri
);
965 cgiSetArray("notify_recipient_name", element
, name
);
970 * Add "admin_uri" variable if we have a "printer_uri_supported"
974 if (!strcmp(name
, "printer_uri_supported"))
976 cgiRewriteURL(attr
->values
[0].string
.text
, value
, sizeof(value
),
979 cgiSetArray("admin_uri", element
, value
);
986 value
[0] = '\0'; /* Initially an empty string */
987 valptr
= value
; /* Start at the beginning */
989 for (i
= 0; i
< attr
->num_values
; i
++)
992 strlcat(valptr
, ",", sizeof(value
) - (valptr
- value
));
994 valptr
+= strlen(valptr
);
996 switch (attr
->value_tag
)
998 case IPP_TAG_INTEGER
:
1000 if (strncmp(name
, "time_at_", 8) == 0)
1002 time_t t
; /* Temporary time value */
1004 t
= (time_t)attr
->values
[i
].integer
;
1005 date
= localtime(&t
);
1007 strftime(valptr
, sizeof(value
) - (valptr
- value
), "%c", date
);
1010 snprintf(valptr
, sizeof(value
) - (valptr
- value
),
1011 "%d", attr
->values
[i
].integer
);
1014 case IPP_TAG_BOOLEAN
:
1015 snprintf(valptr
, sizeof(value
) - (valptr
- value
),
1016 "%d", attr
->values
[i
].boolean
);
1019 case IPP_TAG_NOVALUE
:
1020 strlcat(valptr
, "novalue", sizeof(value
) - (valptr
- value
));
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
);
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
?
1038 if (strchr(attr
->values
[i
].string
.text
, ':') &&
1039 strcmp(name
, "device_uri"))
1045 if (!strcmp(name
, "member_uris"))
1047 char url
[1024]; /* URL for class member... */
1050 cgiRewriteURL(attr
->values
[i
].string
.text
, url
,
1053 snprintf(valptr
, sizeof(value
) - (valptr
- value
),
1054 "<A HREF=\"%s\">%s</A>", url
,
1055 strrchr(attr
->values
[i
].string
.text
, '/') + 1);
1058 cgiRewriteURL(attr
->values
[i
].string
.text
, valptr
,
1059 sizeof(value
) - (valptr
- value
), NULL
);
1063 case IPP_TAG_STRING
:
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
));
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
,
1081 break; /* anti-compiler-warning-code */
1086 * Add the element...
1089 if (attr
->value_tag
!= IPP_TAG_BEGIN_COLLECTION
)
1091 cgiSetArray(name
, element
, value
);
1093 fprintf(stderr
, "DEBUG2: %s[%d]=\"%s\"\n", name
, element
, value
);
1097 return (attr
? attr
->next
: NULL
);
1102 * 'cgiSetIPPVars()' - Set CGI variables from an IPP response.
1105 int /* O - Maximum number of elements */
1106 cgiSetIPPVars(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 */
1112 int element
; /* Element in CGI array */
1113 ipp_attribute_t
*attr
, /* Attribute in response... */
1114 *filter
; /* Filtering attribute */
1117 fprintf(stderr
, "DEBUG2: cgiSetIPPVars(response=%p, filter_name=\"%s\", "
1118 "filter_value=\"%s\", prefix=\"%s\", parent_el=%d)\n",
1119 response
, filter_name
? filter_name
: "(null)",
1120 filter_value
? filter_value
: "(null)",
1121 prefix
? prefix
: "(null)", parent_el
);
1124 * Set common CGI template variables...
1128 cgiSetServerVersion();
1131 * Loop through the attributes and set them for the template...
1134 attr
= response
->attrs
;
1137 while (attr
&& attr
->group_tag
== IPP_TAG_OPERATION
)
1140 for (element
= parent_el
; attr
; element
++)
1143 * Copy attributes to a separator...
1146 while (attr
&& attr
->group_tag
== IPP_TAG_ZERO
)
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
))
1166 return (element
+ 1);
1168 if (filter
->group_tag
== IPP_TAG_ZERO
)
1176 attr
= cgiSetIPPObjectVars(attr
, prefix
, element
);
1179 fprintf(stderr
, "DEBUG2: Returing %d from cgiSetIPPVars()...\n", element
);
1186 * 'cgiShowIPPError()' - Show the last IPP error message.
1188 * The caller must still call cgiStartHTML() and cgiEndHTML().
1192 cgiShowIPPError(const char *message
) /* I - Contextual message */
1194 cgiSetVariable("MESSAGE", cgiText(message
));
1195 cgiSetVariable("ERROR", cupsLastErrorString());
1196 cgiCopyTemplateLang("error.tmpl");
1201 * 'cgiShowJobs()' - Show print jobs.
1205 cgiShowJobs(http_t
*http
, /* I - Connection to server */
1206 const char *dest
) /* I - Destination name or NULL */
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 */
1225 * Build an IPP_GET_JOBS request, which requires the following
1228 * attributes-charset
1229 * attributes-natural-language
1233 request
= ippNewRequest(IPP_GET_JOBS
);
1237 httpAssembleURIf(HTTP_URI_CODING_ALL
, url
, sizeof(url
), "ipp", NULL
,
1238 "localhost", ippPort(), "/printers/%s", dest
);
1239 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
, "printer-uri",
1243 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
, "job-uri", NULL
,
1244 "ipp://localhost/jobs");
1246 if ((which_jobs
= cgiGetVariable("which_jobs")) != NULL
)
1247 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_KEYWORD
, "which-jobs",
1250 cgiGetAttributes(request
, "jobs.tmpl");
1253 * Do the request and get back a response...
1256 if ((response
= cupsDoRequest(http
, request
, "/")) != NULL
)
1259 * Get a list of matching job objects.
1262 if ((var
= cgiGetVariable("QUERY")) != NULL
)
1263 search
= cgiCompileSearch(var
);
1267 jobs
= cgiGetIPPObjects(response
, search
);
1268 count
= cupsArrayCount(jobs
);
1271 cgiFreeSearch(search
);
1274 * Figure out which jobs to display...
1277 if ((var
= cgiGetVariable("FIRST")) != NULL
)
1283 first
= count
- CUPS_PAGE_MAX
;
1285 first
= (first
/ CUPS_PAGE_MAX
) * CUPS_PAGE_MAX
;
1290 sprintf(url
, "%d", count
);
1291 cgiSetVariable("TOTAL", url
);
1293 if ((var
= cgiGetVariable("ORDER")) != NULL
)
1294 ascending
= !strcasecmp(var
, "asc");
1297 ascending
= !which_jobs
|| !strcasecmp(which_jobs
, "not-completed");
1298 cgiSetVariable("ORDER", ascending
? "asc" : "dec");
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
);
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
);
1317 * Save navigation URLs...
1320 urlend
= url
+ sizeof(url
);
1322 if ((var
= cgiGetVariable("QUERY")) != NULL
)
1325 snprintf(url
, sizeof(url
), "/%s/%s?QUERY=", cgiGetVariable("SECTION"),
1328 strlcpy(url
, "/jobs/?QUERY=", sizeof(url
));
1330 urlptr
= url
+ strlen(url
);
1332 cgiFormEncode(urlptr
, var
, urlend
- urlptr
);
1333 urlptr
+= strlen(urlptr
);
1335 strlcpy(urlptr
, "&", urlend
- urlptr
);
1336 urlptr
+= strlen(urlptr
);
1341 snprintf(url
, sizeof(url
), "/%s/%s?", cgiGetVariable("SECTION"), dest
);
1343 strlcpy(url
, "/jobs/?", sizeof(url
));
1345 urlptr
= url
+ strlen(url
);
1350 strlcpy(urlptr
, "WHICH_JOBS=", urlend
- urlptr
);
1351 urlptr
+= strlen(urlptr
);
1353 cgiFormEncode(urlptr
, which_jobs
, urlend
- urlptr
);
1354 urlptr
+= strlen(urlptr
);
1356 strlcpy(urlptr
, "&", urlend
- urlptr
);
1357 urlptr
+= strlen(urlptr
);
1360 snprintf(urlptr
, urlend
- urlptr
, "FIRST=%d", first
);
1361 cgiSetVariable("THISURL", url
);
1365 snprintf(urlptr
, urlend
- urlptr
, "FIRST=%d&ORDER=%s",
1366 first
- CUPS_PAGE_MAX
, ascending
? "asc" : "dec");
1367 cgiSetVariable("PREVURL", url
);
1370 if ((first
+ CUPS_PAGE_MAX
) < count
)
1372 snprintf(urlptr
, urlend
- urlptr
, "FIRST=%d&ORDER=%s",
1373 first
+ CUPS_PAGE_MAX
, ascending
? "asc" : "dec");
1374 cgiSetVariable("NEXTURL", url
);
1378 * Then show everything...
1382 cgiSetVariable("SEARCH_DEST", dest
);
1384 cgiCopyTemplateLang("search.tmpl");
1386 cgiCopyTemplateLang("jobs-header.tmpl");
1389 cgiCopyTemplateLang("pager.tmpl");
1391 cgiCopyTemplateLang("jobs.tmpl");
1394 cgiCopyTemplateLang("pager.tmpl");
1396 cupsArrayDelete(jobs
);
1397 ippDelete(response
);
1403 * 'cgiText()' - Return localized text.
1406 const char * /* O - Localized message */
1407 cgiText(const char *message
) /* I - Message */
1409 static cups_lang_t
*language
= NULL
;
1414 language
= cupsLangDefault();
1416 return (_cupsLangString(language
, message
));
1421 * End of "$Id: ipp-var.c 6304 2007-02-22 22:06:23Z mike $".