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