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