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