]> git.ipfire.org Git - thirdparty/cups.git/blob - cups/util.c
Merge changes from 1.1.x into 1.2 devel.
[thirdparty/cups.git] / cups / util.c
1 /*
2 * "$Id: util.c,v 1.81.2.3 2001/12/26 16:52:13 mike Exp $"
3 *
4 * Printing utilities for the Common UNIX Printing System (CUPS).
5 *
6 * Copyright 1997-2001 by Easy Software Products.
7 *
8 * These coded instructions, statements, and computer programs are the
9 * property of Easy Software Products and are protected by Federal
10 * copyright law. Distribution and use rights are outlined in the file
11 * "LICENSE.txt" which should have been included with this file. If this
12 * file is missing or damaged please contact Easy Software Products
13 * at:
14 *
15 * Attn: CUPS Licensing Information
16 * Easy Software Products
17 * 44141 Airport View Drive, Suite 204
18 * Hollywood, Maryland 20636-3111 USA
19 *
20 * Voice: (301) 373-9603
21 * EMail: cups-info@cups.org
22 * WWW: http://www.cups.org
23 *
24 * Contents:
25 *
26 * cupsCancelJob() - Cancel a print job.
27 * cupsDoFileRequest() - Do an IPP request...
28 * cupsFreeJobs() - Free memory used by job data.
29 * cupsGetClasses() - Get a list of printer classes.
30 * cupsGetDefault() - Get the default printer or class.
31 * cupsGetJobs() - Get the jobs from the server.
32 * cupsGetPPD() - Get the PPD file for a printer.
33 * cupsGetPrinters() - Get a list of printers.
34 * cupsLastError() - Return the last IPP error that occurred.
35 * cupsPrintFile() - Print a file to a printer or class.
36 * cupsPrintFiles() - Print one or more files to a printer or class.
37 * cups_connect() - Connect to the specified host...
38 * cups_local_auth() - Get the local authorization certificate if
39 * available/applicable...
40 */
41
42 /*
43 * Include necessary headers...
44 */
45
46 #include "cups.h"
47 #include "ipp.h"
48 #include "language.h"
49 #include "string.h"
50 #include "debug.h"
51 #include <stdlib.h>
52 #include <ctype.h>
53 #include <errno.h>
54 #include <fcntl.h>
55 #include <sys/stat.h>
56 #if defined(WIN32) || defined(__EMX__)
57 # include <io.h>
58 #else
59 # include <unistd.h>
60 #endif /* WIN32 || __EMX__ */
61
62
63 /*
64 * Local globals...
65 */
66
67 static http_t *cups_server = NULL; /* Current server connection */
68 static ipp_status_t last_error = IPP_OK; /* Last IPP error */
69 static char authstring[1024] = ""; /* Authorization string */
70
71
72 /*
73 * Local functions...
74 */
75
76 static char *cups_connect(const char *name, char *printer, char *hostname);
77 static int cups_local_auth(http_t *http);
78
79
80 /*
81 * 'cupsCancelJob()' - Cancel a print job.
82 */
83
84 int /* O - 1 on success, 0 on failure */
85 cupsCancelJob(const char *name, /* I - Name of printer or class */
86 int job) /* I - Job ID */
87 {
88 char printer[HTTP_MAX_URI], /* Printer name */
89 hostname[HTTP_MAX_URI], /* Hostname */
90 uri[HTTP_MAX_URI]; /* Printer URI */
91 ipp_t *request, /* IPP request */
92 *response; /* IPP response */
93 cups_lang_t *language; /* Language info */
94
95
96 /*
97 * See if we can connect to the server...
98 */
99
100 if (!cups_connect(name, printer, hostname))
101 {
102 last_error = IPP_SERVICE_UNAVAILABLE;
103 return (0);
104 }
105
106 /*
107 * Build an IPP_CANCEL_JOB request, which requires the following
108 * attributes:
109 *
110 * attributes-charset
111 * attributes-natural-language
112 * printer-uri
113 * job-id
114 * [requesting-user-name]
115 */
116
117 request = ippNew();
118
119 request->request.op.operation_id = IPP_CANCEL_JOB;
120 request->request.op.request_id = 1;
121
122 language = cupsLangDefault();
123
124 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
125 "attributes-charset", NULL, cupsLangEncoding(language));
126
127 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
128 "attributes-natural-language", NULL,
129 language != NULL ? language->language : "C");
130
131 snprintf(uri, sizeof(uri), "ipp://%s:%d/printers/%s", hostname, ippPort(), printer);
132 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
133 NULL, uri);
134
135 ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_INTEGER, "job-id", job);
136
137 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
138 NULL, cupsUser());
139
140 /*
141 * Do the request...
142 */
143
144 if ((response = cupsDoRequest(cups_server, request, "/jobs/")) == NULL)
145 {
146 last_error = IPP_BAD_REQUEST;
147 return (0);
148 }
149 else
150 {
151 last_error = response->request.status.status_code;
152 ippDelete(response);
153
154 return (1);
155 }
156 }
157
158
159 /*
160 * 'cupsDoFileRequest()' - Do an IPP request...
161 */
162
163 ipp_t * /* O - Response data */
164 cupsDoFileRequest(http_t *http, /* I - HTTP connection to server */
165 ipp_t *request, /* I - IPP request */
166 const char *resource, /* I - HTTP resource for POST */
167 const char *filename) /* I - File to send or NULL */
168 {
169 ipp_t *response; /* IPP response data */
170 char length[255]; /* Content-Length field */
171 http_status_t status; /* Status of HTTP request */
172 FILE *file; /* File to send */
173 struct stat fileinfo; /* File information */
174 int bytes; /* Number of bytes read/written */
175 char buffer[32768]; /* Output buffer */
176 const char *password; /* Password string */
177 char realm[HTTP_MAX_VALUE], /* realm="xyz" string */
178 nonce[HTTP_MAX_VALUE], /* nonce="xyz" string */
179 plain[255], /* Plaintext username:password */
180 encode[512]; /* Encoded username:password */
181 char prompt[1024]; /* Prompt string */
182
183
184 if (http == NULL || request == NULL || resource == NULL)
185 {
186 if (request != NULL)
187 ippDelete(request);
188
189 last_error = IPP_INTERNAL_ERROR;
190 return (NULL);
191 }
192
193 DEBUG_printf(("cupsDoFileRequest(%p, %08x, \'%s\', \'%s\')\n",
194 http, request, resource, filename ? filename : "(null)"));
195
196 /*
197 * See if we have a file to send...
198 */
199
200 if (filename != NULL)
201 {
202 if (stat(filename, &fileinfo))
203 {
204 /*
205 * Can't get file information!
206 */
207
208 ippDelete(request);
209 last_error = IPP_NOT_FOUND;
210 return (NULL);
211 }
212
213 if ((file = fopen(filename, "rb")) == NULL)
214 {
215 /*
216 * Can't open file!
217 */
218
219 ippDelete(request);
220 last_error = IPP_NOT_FOUND;
221 return (NULL);
222 }
223 }
224 else
225 file = NULL;
226
227 /*
228 * Loop until we can send the request without authorization problems.
229 */
230
231 response = NULL;
232 status = HTTP_ERROR;
233
234 while (response == NULL)
235 {
236 DEBUG_puts("cupsDoFileRequest: setup...");
237
238 /*
239 * Setup the HTTP variables needed...
240 */
241
242 if (filename != NULL)
243 sprintf(length, "%lu", (unsigned long)(ippLength(request) +
244 (size_t)fileinfo.st_size));
245 else
246 sprintf(length, "%lu", (unsigned long)ippLength(request));
247
248 httpClearFields(http);
249 httpSetField(http, HTTP_FIELD_CONTENT_LENGTH, length);
250 httpSetField(http, HTTP_FIELD_CONTENT_TYPE, "application/ipp");
251 httpSetField(http, HTTP_FIELD_AUTHORIZATION, authstring);
252
253 /*
254 * Try the request...
255 */
256
257 DEBUG_puts("cupsDoFileRequest: post...");
258
259 if (httpPost(http, resource))
260 {
261 if (httpReconnect(http))
262 {
263 status = HTTP_ERROR;
264 break;
265 }
266 else
267 continue;
268 }
269
270 /*
271 * Send the IPP data and wait for the response...
272 */
273
274 DEBUG_puts("cupsDoFileRequest: ipp write...");
275
276 request->state = IPP_IDLE;
277 if (ippWrite(http, request) != IPP_ERROR)
278 if (filename != NULL)
279 {
280 DEBUG_puts("cupsDoFileRequest: file write...");
281
282 /*
283 * Send the file...
284 */
285
286 rewind(file);
287
288 while ((bytes = fread(buffer, 1, sizeof(buffer), file)) > 0)
289 if (httpWrite(http, buffer, bytes) < bytes)
290 break;
291 }
292
293 /*
294 * Get the server's return status...
295 */
296
297 DEBUG_puts("cupsDoFileRequest: update...");
298
299 while ((status = httpUpdate(http)) == HTTP_CONTINUE);
300
301 if (status == HTTP_UNAUTHORIZED)
302 {
303 DEBUG_puts("cupsDoFileRequest: unauthorized...");
304
305 /*
306 * Flush any error message...
307 */
308
309 httpFlush(http);
310
311 /*
312 * See if we can do local authentication...
313 */
314
315 if (cups_local_auth(http))
316 continue;
317
318 /*
319 * Nope - get a password from the user...
320 */
321
322 snprintf(prompt, sizeof(prompt), "Password for %s on %s? ", cupsUser(),
323 http->hostname);
324
325 if ((password = cupsGetPassword(prompt)) != NULL)
326 {
327 /*
328 * Got a password; send it to the server...
329 */
330
331 if (!password[0])
332 break;
333
334 if (strncmp(http->fields[HTTP_FIELD_WWW_AUTHENTICATE], "Basic", 5) == 0)
335 {
336 /*
337 * Basic authentication...
338 */
339
340 snprintf(plain, sizeof(plain), "%s:%s", cupsUser(), password);
341 httpEncode64(encode, plain);
342 snprintf(authstring, sizeof(authstring), "Basic %s", encode);
343 }
344 else
345 {
346 /*
347 * Digest authentication...
348 */
349
350 httpGetSubField(http, HTTP_FIELD_WWW_AUTHENTICATE, "realm", realm);
351 httpGetSubField(http, HTTP_FIELD_WWW_AUTHENTICATE, "nonce", nonce);
352
353 httpMD5(cupsUser(), realm, password, encode);
354 httpMD5Final(nonce, "POST", resource, encode);
355 snprintf(authstring, sizeof(authstring),
356 "Digest username=\"%s\", realm=\"%s\", nonce=\"%s\", "
357 "response=\"%s\"", cupsUser(), realm, nonce, encode);
358 }
359 continue;
360 }
361 else
362 break;
363 }
364 else if (status == HTTP_ERROR)
365 {
366 #if defined(WIN32) || defined(__EMX__)
367 if (http->error != WSAENETDOWN && http->error != WSAENETUNREACH)
368 #else
369 if (http->error != ENETDOWN && http->error != ENETUNREACH)
370 #endif /* WIN32 || __EMX__ */
371 continue;
372 else
373 break;
374 }
375 #ifdef HAVE_LIBSSL
376 else if (status == HTTP_UPGRADE_REQUIRED)
377 {
378 /*
379 * Flush any error message...
380 */
381
382 httpFlush(http);
383
384 /*
385 * Try again, this time with encryption enabled...
386 */
387
388 continue;
389 }
390 #endif /* HAVE_LIBSSL */
391 else if (status != HTTP_OK)
392 {
393 DEBUG_printf(("cupsDoFileRequest: error %d...\n", status));
394
395 /*
396 * Flush any error message...
397 */
398
399 httpFlush(http);
400 break;
401 }
402 else
403 {
404 /*
405 * Read the response...
406 */
407
408 DEBUG_puts("cupsDoFileRequest: response...");
409
410 response = ippNew();
411
412 if (ippRead(http, response) == IPP_ERROR)
413 {
414 /*
415 * Delete the response...
416 */
417
418 ippDelete(response);
419 response = NULL;
420
421 last_error = IPP_SERVICE_UNAVAILABLE;
422 break;
423 }
424 }
425 }
426
427 /*
428 * Close the file if needed...
429 */
430
431 if (filename != NULL)
432 fclose(file);
433
434 /*
435 * Flush any remaining data...
436 */
437
438 httpFlush(http);
439
440 /*
441 * Delete the original request and return the response...
442 */
443
444 ippDelete(request);
445
446 if (response)
447 last_error = response->request.status.status_code;
448 else if (status == HTTP_NOT_FOUND)
449 last_error = IPP_NOT_FOUND;
450 else if (status == HTTP_UNAUTHORIZED)
451 last_error = IPP_NOT_AUTHORIZED;
452 else if (status != HTTP_OK)
453 last_error = IPP_SERVICE_UNAVAILABLE;
454
455 return (response);
456 }
457
458
459 /*
460 * 'cupsFreeJobs()' - Free memory used by job data.
461 */
462
463 void
464 cupsFreeJobs(int num_jobs,/* I - Number of jobs */
465 cups_job_t *jobs) /* I - Jobs */
466 {
467 int i; /* Looping var */
468
469
470 if (num_jobs <= 0 || jobs == NULL)
471 return;
472
473 for (i = 0; i < num_jobs; i ++)
474 {
475 free(jobs[i].dest);
476 free(jobs[i].user);
477 free(jobs[i].format);
478 free(jobs[i].title);
479 }
480
481 free(jobs);
482 }
483
484
485 /*
486 * 'cupsGetClasses()' - Get a list of printer classes.
487 */
488
489 int /* O - Number of classes */
490 cupsGetClasses(char ***classes) /* O - Classes */
491 {
492 int n; /* Number of classes */
493 ipp_t *request, /* IPP Request */
494 *response; /* IPP Response */
495 ipp_attribute_t *attr; /* Current attribute */
496 cups_lang_t *language; /* Default language */
497 char **temp; /* Temporary pointer */
498
499
500 if (classes == NULL)
501 {
502 last_error = IPP_INTERNAL_ERROR;
503 return (0);
504 }
505
506 /*
507 * Try to connect to the server...
508 */
509
510 if (!cups_connect("default", NULL, NULL))
511 {
512 last_error = IPP_SERVICE_UNAVAILABLE;
513 return (0);
514 }
515
516 /*
517 * Build a CUPS_GET_CLASSES request, which requires the following
518 * attributes:
519 *
520 * attributes-charset
521 * attributes-natural-language
522 * requested-attributes
523 */
524
525 request = ippNew();
526
527 request->request.op.operation_id = CUPS_GET_CLASSES;
528 request->request.op.request_id = 1;
529
530 language = cupsLangDefault();
531
532 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
533 "attributes-charset", NULL, cupsLangEncoding(language));
534
535 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
536 "attributes-natural-language", NULL, language->language);
537
538 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
539 "requested-attributes", NULL, "printer-name");
540
541 /*
542 * Do the request and get back a response...
543 */
544
545 n = 0;
546 *classes = NULL;
547
548 if ((response = cupsDoRequest(cups_server, request, "/")) != NULL)
549 {
550 last_error = response->request.status.status_code;
551
552 for (attr = response->attrs; attr != NULL; attr = attr->next)
553 if (attr->name != NULL &&
554 strcasecmp(attr->name, "printer-name") == 0 &&
555 attr->value_tag == IPP_TAG_NAME)
556 {
557 if (n == 0)
558 temp = malloc(sizeof(char *));
559 else
560 temp = realloc(*classes, sizeof(char *) * (n + 1));
561
562 if (temp == NULL)
563 {
564 /*
565 * Ran out of memory!
566 */
567
568 while (n > 0)
569 {
570 n --;
571 free((*classes)[n]);
572 }
573
574 free(*classes);
575 ippDelete(response);
576 return (0);
577 }
578
579 *classes = temp;
580 temp[n] = strdup(attr->values[0].string.text);
581 n ++;
582 }
583
584 ippDelete(response);
585 }
586 else
587 last_error = IPP_BAD_REQUEST;
588
589 return (n);
590 }
591
592
593 /*
594 * 'cupsGetDefault()' - Get the default printer or class.
595 */
596
597 const char * /* O - Default printer or NULL */
598 cupsGetDefault(void)
599 {
600 ipp_t *request, /* IPP Request */
601 *response; /* IPP Response */
602 ipp_attribute_t *attr; /* Current attribute */
603 cups_lang_t *language; /* Default language */
604 const char *var; /* Environment variable */
605 static char def_printer[256];/* Default printer */
606
607
608 /*
609 * First see if the LPDEST or PRINTER environment variables are
610 * set... However, if PRINTER is set to "lp", ignore it to work
611 * around a "feature" in most Linux distributions - the default
612 * user login scripts set PRINTER to "lp"...
613 */
614
615 if ((var = getenv("LPDEST")) != NULL)
616 return (var);
617 else if ((var = getenv("PRINTER")) != NULL && strcmp(var, "lp") != 0)
618 return (var);
619
620 /*
621 * Try to connect to the server...
622 */
623
624 if (!cups_connect("default", NULL, NULL))
625 {
626 last_error = IPP_SERVICE_UNAVAILABLE;
627 return (NULL);
628 }
629
630 /*
631 * Build a CUPS_GET_DEFAULT request, which requires the following
632 * attributes:
633 *
634 * attributes-charset
635 * attributes-natural-language
636 */
637
638 request = ippNew();
639
640 request->request.op.operation_id = CUPS_GET_DEFAULT;
641 request->request.op.request_id = 1;
642
643 language = cupsLangDefault();
644
645 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
646 "attributes-charset", NULL, cupsLangEncoding(language));
647
648 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
649 "attributes-natural-language", NULL, language->language);
650
651 /*
652 * Do the request and get back a response...
653 */
654
655 if ((response = cupsDoRequest(cups_server, request, "/")) != NULL)
656 {
657 last_error = response->request.status.status_code;
658
659 if ((attr = ippFindAttribute(response, "printer-name", IPP_TAG_NAME)) != NULL)
660 {
661 strncpy(def_printer, attr->values[0].string.text, sizeof(def_printer) - 1);
662 def_printer[sizeof(def_printer) - 1] = '\0';
663 ippDelete(response);
664 return (def_printer);
665 }
666
667 ippDelete(response);
668 }
669 else
670 last_error = IPP_BAD_REQUEST;
671
672 return (NULL);
673 }
674
675
676 /*
677 * 'cupsGetJobs()' - Get the jobs from the server.
678 */
679
680 int /* O - Number of jobs */
681 cupsGetJobs(cups_job_t **jobs, /* O - Job data */
682 const char *mydest, /* I - Only show jobs for dest? */
683 int myjobs, /* I - Only show my jobs? */
684 int completed) /* I - Only show completed jobs? */
685 {
686 int n; /* Number of jobs */
687 ipp_t *request, /* IPP Request */
688 *response; /* IPP Response */
689 ipp_attribute_t *attr; /* Current attribute */
690 cups_lang_t *language; /* Default language */
691 cups_job_t *temp; /* Temporary pointer */
692 int id, /* job-id */
693 priority, /* job-priority */
694 size; /* job-k-octets */
695 ipp_jstate_t state; /* job-state */
696 time_t completed_time, /* time-at-completed */
697 creation_time, /* time-at-creation */
698 processing_time; /* time-at-processing */
699 const char *dest, /* job-printer-uri */
700 *format, /* document-format */
701 *title, /* job-name */
702 *user; /* job-originating-user-name */
703 char uri[HTTP_MAX_URI]; /* URI for jobs */
704 static const char *attrs[] = /* Requested attributes */
705 {
706 "job-id",
707 "job-priority",
708 "job-k-octets",
709 "job-state",
710 "time-at-completed",
711 "time-at-creation",
712 "time-at-processing",
713 "job-printer-uri",
714 "document-format",
715 "job-name",
716 "job-originating-user-name"
717 };
718
719
720 if (jobs == NULL)
721 {
722 last_error = IPP_INTERNAL_ERROR;
723 return (0);
724 }
725
726 /*
727 * Try to connect to the server...
728 */
729
730 if (!cups_connect("default", NULL, NULL))
731 {
732 last_error = IPP_SERVICE_UNAVAILABLE;
733 return (0);
734 }
735
736 /*
737 * Build an IPP_GET_JOBS request, which requires the following
738 * attributes:
739 *
740 * attributes-charset
741 * attributes-natural-language
742 * printer-uri
743 * requesting-user-name
744 * which-jobs
745 * my-jobs
746 * requested-attributes
747 */
748
749 request = ippNew();
750
751 request->request.op.operation_id = IPP_GET_JOBS;
752 request->request.op.request_id = 1;
753
754 language = cupsLangDefault();
755
756 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
757 "attributes-charset", NULL, cupsLangEncoding(language));
758
759 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
760 "attributes-natural-language", NULL, language->language);
761
762 if (mydest)
763 snprintf(uri, sizeof(uri), "ipp://localhost/printers/%s", mydest);
764 else
765 strcpy(uri, "ipp://localhost/jobs");
766
767 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
768 "printer-uri", NULL, uri);
769
770 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
771 "requesting-user-name", NULL, cupsUser());
772
773 if (myjobs)
774 ippAddBoolean(request, IPP_TAG_OPERATION, "my-jobs", 1);
775
776 if (completed)
777 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
778 "which-jobs", NULL, "completed");
779
780 ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
781 "requested-attributes", sizeof(attrs) / sizeof(attrs[0]),
782 NULL, attrs);
783
784 /*
785 * Do the request and get back a response...
786 */
787
788 n = 0;
789 *jobs = NULL;
790
791 if ((response = cupsDoRequest(cups_server, request, "/")) != NULL)
792 {
793 last_error = response->request.status.status_code;
794
795 for (attr = response->attrs; attr != NULL; attr = attr->next)
796 {
797 /*
798 * Skip leading attributes until we hit a job...
799 */
800
801 while (attr != NULL && attr->group_tag != IPP_TAG_JOB)
802 attr = attr->next;
803
804 if (attr == NULL)
805 break;
806
807 /*
808 * Pull the needed attributes from this job...
809 */
810
811 id = 0;
812 size = 0;
813 priority = 50;
814 state = IPP_JOB_PENDING;
815 user = NULL;
816 dest = NULL;
817 format = NULL;
818 title = NULL;
819 creation_time = 0;
820 completed_time = 0;
821 processing_time = 0;
822
823 while (attr != NULL && attr->group_tag == IPP_TAG_JOB)
824 {
825 if (strcmp(attr->name, "job-id") == 0 &&
826 attr->value_tag == IPP_TAG_INTEGER)
827 id = attr->values[0].integer;
828 else if (strcmp(attr->name, "job-state") == 0 &&
829 attr->value_tag == IPP_TAG_ENUM)
830 state = (ipp_jstate_t)attr->values[0].integer;
831 else if (strcmp(attr->name, "job-priority") == 0 &&
832 attr->value_tag == IPP_TAG_INTEGER)
833 priority = attr->values[0].integer;
834 else if (strcmp(attr->name, "job-k-octets") == 0 &&
835 attr->value_tag == IPP_TAG_INTEGER)
836 size = attr->values[0].integer;
837 else if (strcmp(attr->name, "time-at-completed") == 0 &&
838 attr->value_tag == IPP_TAG_INTEGER)
839 completed_time = attr->values[0].integer;
840 else if (strcmp(attr->name, "time-at-creation") == 0 &&
841 attr->value_tag == IPP_TAG_INTEGER)
842 creation_time = attr->values[0].integer;
843 else if (strcmp(attr->name, "time-at-processing") == 0 &&
844 attr->value_tag == IPP_TAG_INTEGER)
845 processing_time = attr->values[0].integer;
846 else if (strcmp(attr->name, "job-printer-uri") == 0 &&
847 attr->value_tag == IPP_TAG_URI)
848 {
849 if ((dest = strrchr(attr->values[0].string.text, '/')) != NULL)
850 dest ++;
851 }
852 else if (strcmp(attr->name, "job-originating-user-name") == 0 &&
853 attr->value_tag == IPP_TAG_NAME)
854 user = attr->values[0].string.text;
855 else if (strcmp(attr->name, "document-format") == 0 &&
856 attr->value_tag == IPP_TAG_MIMETYPE)
857 format = attr->values[0].string.text;
858 else if (strcmp(attr->name, "job-name") == 0 &&
859 attr->value_tag == IPP_TAG_TEXT)
860 title = attr->values[0].string.text;
861
862 attr = attr->next;
863 }
864
865 /*
866 * See if we have everything needed...
867 */
868
869 if (dest == NULL || format == NULL || title == NULL || user == NULL ||
870 id == 0)
871 {
872 if (attr == NULL)
873 break;
874 else
875 continue;
876 }
877
878 /*
879 * Allocate memory for the job...
880 */
881
882 if (n == 0)
883 temp = malloc(sizeof(cups_job_t));
884 else
885 temp = realloc(*jobs, sizeof(cups_job_t) * (n + 1));
886
887 if (temp == NULL)
888 {
889 /*
890 * Ran out of memory!
891 */
892
893 cupsFreeJobs(n, *jobs);
894 *jobs = NULL;
895
896 ippDelete(response);
897 return (0);
898 }
899
900 *jobs = temp;
901 temp += n;
902 n ++;
903
904 /*
905 * Copy the data over...
906 */
907
908 temp->dest = strdup(dest);
909 temp->user = strdup(user);
910 temp->format = strdup(format);
911 temp->title = strdup(title);
912 temp->id = id;
913 temp->priority = priority;
914 temp->state = state;
915 temp->size = size;
916 temp->completed_time = completed_time;
917 temp->creation_time = creation_time;
918 temp->processing_time = processing_time;
919 }
920
921 ippDelete(response);
922 }
923 else
924 last_error = IPP_BAD_REQUEST;
925
926 return (n);
927 }
928
929
930 /*
931 * 'cupsGetPPD()' - Get the PPD file for a printer.
932 */
933
934 const char * /* O - Filename for PPD file */
935 cupsGetPPD(const char *name) /* I - Printer name */
936 {
937 int i; /* Looping var */
938 ipp_t *request, /* IPP request */
939 *response; /* IPP response */
940 ipp_attribute_t *attr; /* Current attribute */
941 cups_lang_t *language; /* Local language */
942 int fd; /* PPD file */
943 int bytes; /* Number of bytes read */
944 char buffer[8192]; /* Buffer for file */
945 char printer[HTTP_MAX_URI], /* Printer name */
946 method[HTTP_MAX_URI], /* Method/scheme name */
947 username[HTTP_MAX_URI], /* Username:password */
948 hostname[HTTP_MAX_URI], /* Hostname */
949 resource[HTTP_MAX_URI]; /* Resource name */
950 int port; /* Port number */
951 const char *password; /* Password string */
952 char realm[HTTP_MAX_VALUE], /* realm="xyz" string */
953 nonce[HTTP_MAX_VALUE], /* nonce="xyz" string */
954 plain[255], /* Plaintext username:password */
955 encode[512]; /* Encoded username:password */
956 http_status_t status; /* HTTP status from server */
957 char prompt[1024]; /* Prompt string */
958 static char filename[HTTP_MAX_URI]; /* Local filename */
959 static const char *requested_attrs[] =/* Requested attributes */
960 {
961 "printer-uri-supported",
962 "printer-type",
963 "member-uris"
964 };
965
966
967 if (name == NULL)
968 {
969 last_error = IPP_INTERNAL_ERROR;
970 return (NULL);
971 }
972
973 /*
974 * See if we can connect to the server...
975 */
976
977 if (!cups_connect(name, printer, hostname))
978 {
979 last_error = IPP_SERVICE_UNAVAILABLE;
980 return (NULL);
981 }
982
983 /*
984 * Build an IPP_GET_PRINTER_ATTRIBUTES request, which requires the following
985 * attributes:
986 *
987 * attributes-charset
988 * attributes-natural-language
989 * printer-uri
990 * requested-attributes
991 */
992
993 request = ippNew();
994
995 request->request.op.operation_id = IPP_GET_PRINTER_ATTRIBUTES;
996 request->request.op.request_id = 1;
997
998 language = cupsLangDefault();
999
1000 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
1001 "attributes-charset", NULL, cupsLangEncoding(language));
1002
1003 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
1004 "attributes-natural-language", NULL, language->language);
1005
1006 snprintf(buffer, sizeof(buffer), "ipp://localhost/printers/%s", name);
1007 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
1008 "printer-uri", NULL, buffer);
1009
1010 ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
1011 "requested-attributes",
1012 sizeof(requested_attrs) / sizeof(requested_attrs[0]),
1013 NULL, requested_attrs);
1014
1015 /*
1016 * Do the request and get back a response...
1017 */
1018
1019 if ((response = cupsDoRequest(cups_server, request, "/")) != NULL)
1020 {
1021 last_error = response->request.status.status_code;
1022 printer[0] = '\0';
1023 hostname[0] = '\0';
1024
1025 if ((attr = ippFindAttribute(response, "member-uris", IPP_TAG_URI)) != NULL)
1026 {
1027 /*
1028 * Get the first actual server and printer name in the class...
1029 */
1030
1031 for (i = 0; i < attr->num_values; i ++)
1032 {
1033 httpSeparate(attr->values[0].string.text, method, username, hostname,
1034 &port, resource);
1035 if (strncmp(resource, "/printers/", 10) == 0)
1036 {
1037 /*
1038 * Found a printer!
1039 */
1040
1041 strncpy(printer, resource + 10, sizeof(printer) - 1);
1042 printer[sizeof(printer) - 1] = '\0';
1043 break;
1044 }
1045 }
1046 }
1047 else if ((attr = ippFindAttribute(response, "printer-uri-supported",
1048 IPP_TAG_URI)) != NULL)
1049 {
1050 /*
1051 * Get the actual server and printer names...
1052 */
1053
1054 httpSeparate(attr->values[0].string.text, method, username, hostname,
1055 &port, resource);
1056 strncpy(printer, strrchr(resource, '/') + 1, sizeof(printer) - 1);
1057 printer[sizeof(printer) - 1] = '\0';
1058 }
1059
1060 ippDelete(response);
1061
1062 /*
1063 * Remap local hostname to localhost...
1064 */
1065
1066 gethostname(buffer, sizeof(buffer));
1067
1068 if (strcasecmp(buffer, hostname) == 0)
1069 strcpy(hostname, "localhost");
1070 }
1071
1072 cupsLangFree(language);
1073
1074 if (!printer[0])
1075 return (NULL);
1076
1077 /*
1078 * Reconnect to the correct server as needed...
1079 */
1080
1081 if (strcasecmp(cups_server->hostname, hostname) != 0)
1082 {
1083 httpClose(cups_server);
1084
1085 if ((cups_server = httpConnectEncrypt(hostname, ippPort(),
1086 cupsEncryption())) == NULL)
1087 {
1088 last_error = IPP_SERVICE_UNAVAILABLE;
1089 return (NULL);
1090 }
1091 }
1092
1093 /*
1094 * Get a temp file...
1095 */
1096
1097 if ((fd = cupsTempFd(filename, sizeof(filename))) < 0)
1098 {
1099 /*
1100 * Can't open file; close the server connection and return NULL...
1101 */
1102
1103 httpFlush(cups_server);
1104 httpClose(cups_server);
1105 cups_server = NULL;
1106 return (NULL);
1107 }
1108
1109 /*
1110 * And send a request to the HTTP server...
1111 */
1112
1113 snprintf(resource, sizeof(resource), "/printers/%s.ppd", printer);
1114
1115 do
1116 {
1117 httpClearFields(cups_server);
1118 httpSetField(cups_server, HTTP_FIELD_HOST, hostname);
1119 httpSetField(cups_server, HTTP_FIELD_AUTHORIZATION, authstring);
1120
1121 if (httpGet(cups_server, resource))
1122 {
1123 if (httpReconnect(cups_server))
1124 {
1125 status = HTTP_ERROR;
1126 break;
1127 }
1128 else
1129 {
1130 status = HTTP_UNAUTHORIZED;
1131 continue;
1132 }
1133 }
1134
1135 while ((status = httpUpdate(cups_server)) == HTTP_CONTINUE);
1136
1137 if (status == HTTP_UNAUTHORIZED)
1138 {
1139 DEBUG_puts("cupsGetPPD: unauthorized...");
1140
1141 /*
1142 * Flush any error message...
1143 */
1144
1145 httpFlush(cups_server);
1146
1147 /*
1148 * See if we can do local authentication...
1149 */
1150
1151 if (cups_local_auth(cups_server))
1152 continue;
1153
1154 /*
1155 * Nope, get a password from the user...
1156 */
1157
1158 snprintf(prompt, sizeof(prompt), "Password for %s on %s? ", cupsUser(),
1159 cups_server->hostname);
1160
1161 if ((password = cupsGetPassword(prompt)) != NULL)
1162 {
1163 /*
1164 * Got a password; send it to the server...
1165 */
1166
1167 if (!password[0])
1168 break;
1169
1170 if (strncmp(cups_server->fields[HTTP_FIELD_WWW_AUTHENTICATE], "Basic", 5) == 0)
1171 {
1172 /*
1173 * Basic authentication...
1174 */
1175
1176 snprintf(plain, sizeof(plain), "%s:%s", cupsUser(), password);
1177 httpEncode64(encode, plain);
1178 snprintf(authstring, sizeof(authstring), "Basic %s", encode);
1179 }
1180 else
1181 {
1182 /*
1183 * Digest authentication...
1184 */
1185
1186 httpGetSubField(cups_server, HTTP_FIELD_WWW_AUTHENTICATE, "realm", realm);
1187 httpGetSubField(cups_server, HTTP_FIELD_WWW_AUTHENTICATE, "nonce", nonce);
1188
1189 httpMD5(cupsUser(), realm, password, encode);
1190 httpMD5Final(nonce, "GET", resource, encode);
1191 snprintf(authstring, sizeof(authstring),
1192 "Digest username=\"%s\", realm=\"%s\", nonce=\"%s\", "
1193 "response=\"%s\"", cupsUser(), realm, nonce, encode);
1194 }
1195 continue;
1196 }
1197 else
1198 break;
1199 }
1200 }
1201 while (status == HTTP_UNAUTHORIZED || status == HTTP_UPGRADE_REQUIRED);
1202
1203 /*
1204 * See if we actually got the file or an error...
1205 */
1206
1207 if (status != HTTP_OK)
1208 {
1209 unlink(filename);
1210 httpFlush(cups_server);
1211 httpClose(cups_server);
1212 cups_server = NULL;
1213 return (NULL);
1214 }
1215
1216 /*
1217 * OK, we need to copy the file...
1218 */
1219
1220 while ((bytes = httpRead(cups_server, buffer, sizeof(buffer))) > 0)
1221 write(fd, buffer, bytes);
1222
1223 close(fd);
1224
1225 return (filename);
1226 }
1227
1228
1229 /*
1230 * 'cupsGetPrinters()' - Get a list of printers.
1231 */
1232
1233 int /* O - Number of printers */
1234 cupsGetPrinters(char ***printers) /* O - Printers */
1235 {
1236 int n; /* Number of printers */
1237 ipp_t *request, /* IPP Request */
1238 *response; /* IPP Response */
1239 ipp_attribute_t *attr; /* Current attribute */
1240 cups_lang_t *language; /* Default language */
1241 char **temp; /* Temporary pointer */
1242
1243
1244 if (printers == NULL)
1245 {
1246 last_error = IPP_INTERNAL_ERROR;
1247 return (0);
1248 }
1249
1250 /*
1251 * Try to connect to the server...
1252 */
1253
1254 if (!cups_connect("default", NULL, NULL))
1255 {
1256 last_error = IPP_SERVICE_UNAVAILABLE;
1257 return (0);
1258 }
1259
1260 /*
1261 * Build a CUPS_GET_PRINTERS request, which requires the following
1262 * attributes:
1263 *
1264 * attributes-charset
1265 * attributes-natural-language
1266 * requested-attributes
1267 */
1268
1269 request = ippNew();
1270
1271 request->request.op.operation_id = CUPS_GET_PRINTERS;
1272 request->request.op.request_id = 1;
1273
1274 language = cupsLangDefault();
1275
1276 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
1277 "attributes-charset", NULL, cupsLangEncoding(language));
1278
1279 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
1280 "attributes-natural-language", NULL, language->language);
1281
1282 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
1283 "requested-attributes", NULL, "printer-name");
1284
1285 /*
1286 * Do the request and get back a response...
1287 */
1288
1289 n = 0;
1290 *printers = NULL;
1291
1292 if ((response = cupsDoRequest(cups_server, request, "/")) != NULL)
1293 {
1294 last_error = response->request.status.status_code;
1295
1296 for (attr = response->attrs; attr != NULL; attr = attr->next)
1297 if (attr->name != NULL &&
1298 strcasecmp(attr->name, "printer-name") == 0 &&
1299 attr->value_tag == IPP_TAG_NAME)
1300 {
1301 if (n == 0)
1302 temp = malloc(sizeof(char *));
1303 else
1304 temp = realloc(*printers, sizeof(char *) * (n + 1));
1305
1306 if (temp == NULL)
1307 {
1308 /*
1309 * Ran out of memory!
1310 */
1311
1312 while (n > 0)
1313 {
1314 n --;
1315 free((*printers)[n]);
1316 }
1317
1318 free(*printers);
1319 ippDelete(response);
1320 return (0);
1321 }
1322
1323 *printers = temp;
1324 temp[n] = strdup(attr->values[0].string.text);
1325 n ++;
1326 }
1327
1328 ippDelete(response);
1329 }
1330 else
1331 last_error = IPP_BAD_REQUEST;
1332
1333 return (n);
1334 }
1335
1336
1337 /*
1338 * 'cupsLastError()' - Return the last IPP error that occurred.
1339 */
1340
1341 ipp_status_t /* O - IPP error code */
1342 cupsLastError(void)
1343 {
1344 return (last_error);
1345 }
1346
1347
1348 /*
1349 * 'cupsPrintFile()' - Print a file to a printer or class.
1350 */
1351
1352 int /* O - Job ID */
1353 cupsPrintFile(const char *name, /* I - Printer or class name */
1354 const char *filename, /* I - File to print */
1355 const char *title, /* I - Title of job */
1356 int num_options,/* I - Number of options */
1357 cups_option_t *options) /* I - Options */
1358 {
1359 DEBUG_printf(("cupsPrintFile(\'%s\', \'%s\', %d, %p)\n",
1360 name, filename, num_options, options));
1361
1362 return (cupsPrintFiles(name, 1, &filename, title, num_options, options));
1363 }
1364
1365
1366 /*
1367 * 'cupsPrintFiles()' - Print one or more files to a printer or class.
1368 */
1369
1370 int /* O - Job ID */
1371 cupsPrintFiles(const char *name, /* I - Printer or class name */
1372 int num_files, /* I - Number of files */
1373 const char **files, /* I - File(s) to print */
1374 const char *title, /* I - Title of job */
1375 int num_options,/* I - Number of options */
1376 cups_option_t *options) /* I - Options */
1377 {
1378 int i; /* Looping var */
1379 const char *val; /* Pointer to option value */
1380 ipp_t *request; /* IPP request */
1381 ipp_t *response; /* IPP response */
1382 ipp_attribute_t *attr; /* IPP job-id attribute */
1383 char hostname[HTTP_MAX_URI], /* Hostname */
1384 printer[HTTP_MAX_URI], /* Printer or class name */
1385 uri[HTTP_MAX_URI]; /* Printer URI */
1386 cups_lang_t *language; /* Language to use */
1387 int jobid; /* New job ID */
1388
1389
1390 DEBUG_printf(("cupsPrintFiles(\'%s\', %d, %p, %d, %p)\n",
1391 name, num_files, files, num_options, options));
1392
1393 if (name == NULL || num_files < 1 || files == NULL)
1394 return (0);
1395
1396 /*
1397 * Setup a connection and request data...
1398 */
1399
1400 if (!cups_connect(name, printer, hostname))
1401 {
1402 DEBUG_printf(("cupsPrintFile: Unable to open connection - %s.\n",
1403 strerror(errno)));
1404 last_error = IPP_SERVICE_UNAVAILABLE;
1405 return (0);
1406 }
1407
1408 language = cupsLangDefault();
1409
1410 /*
1411 * Build a standard CUPS URI for the printer and fill the standard IPP
1412 * attributes...
1413 */
1414
1415 if ((request = ippNew()) == NULL)
1416 return (0);
1417
1418 request->request.op.operation_id = num_files == 1 ? IPP_PRINT_JOB :
1419 IPP_CREATE_JOB;
1420 request->request.op.request_id = 1;
1421
1422 snprintf(uri, sizeof(uri), "ipp://%s:%d/printers/%s", hostname, ippPort(), printer);
1423
1424 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
1425 "attributes-charset", NULL, cupsLangEncoding(language));
1426
1427 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
1428 "attributes-natural-language", NULL,
1429 language != NULL ? language->language : "C");
1430
1431 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
1432 NULL, uri);
1433
1434 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
1435 NULL, cupsUser());
1436
1437 if (title)
1438 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "job-name", NULL, title);
1439
1440 /*
1441 * Then add all options...
1442 */
1443
1444 cupsEncodeOptions(request, num_options, options);
1445
1446 /*
1447 * Do the request...
1448 */
1449
1450 snprintf(uri, sizeof(uri), "/printers/%s", printer);
1451
1452 if (num_files == 1)
1453 response = cupsDoFileRequest(cups_server, request, uri, *files);
1454 else
1455 response = cupsDoRequest(cups_server, request, uri);
1456
1457 if (response == NULL)
1458 jobid = 0;
1459 else if (response->request.status.status_code > IPP_OK_CONFLICT)
1460 {
1461 DEBUG_printf(("IPP response code was 0x%x!\n",
1462 response->request.status.status_code));
1463 jobid = 0;
1464 }
1465 else if ((attr = ippFindAttribute(response, "job-id", IPP_TAG_INTEGER)) == NULL)
1466 {
1467 DEBUG_puts("No job ID!");
1468 jobid = 0;
1469 }
1470 else
1471 jobid = attr->values[0].integer;
1472
1473 if (response != NULL)
1474 ippDelete(response);
1475
1476 /*
1477 * Handle multiple file jobs if the create-job operation worked...
1478 */
1479
1480 if (jobid > 0 && num_files > 1)
1481 for (i = 0; i < num_files; i ++)
1482 {
1483 /*
1484 * Build a standard CUPS URI for the job and fill the standard IPP
1485 * attributes...
1486 */
1487
1488 if ((request = ippNew()) == NULL)
1489 return (0);
1490
1491 request->request.op.operation_id = IPP_SEND_DOCUMENT;
1492 request->request.op.request_id = 1;
1493
1494 snprintf(uri, sizeof(uri), "ipp://%s:%d/jobs/%d", hostname, ippPort(),
1495 jobid);
1496
1497 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
1498 "attributes-charset", NULL, cupsLangEncoding(language));
1499
1500 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
1501 "attributes-natural-language", NULL,
1502 language != NULL ? language->language : "C");
1503
1504 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri",
1505 NULL, uri);
1506
1507 /*
1508 * Handle raw print files...
1509 */
1510
1511 if (cupsGetOption("raw", num_options, options))
1512 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_MIMETYPE, "document-format",
1513 NULL, "application/vnd.cups-raw");
1514 else if ((val = cupsGetOption("document-format", num_options, options)) != NULL)
1515 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_MIMETYPE, "document-format",
1516 NULL, val);
1517 else
1518 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_MIMETYPE, "document-format",
1519 NULL, "application/octet-stream");
1520
1521 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
1522 NULL, cupsUser());
1523
1524 /*
1525 * Is this the last document?
1526 */
1527
1528 if (i == (num_files - 1))
1529 ippAddBoolean(request, IPP_TAG_OPERATION, "last-document", 1);
1530
1531 /*
1532 * Send the file...
1533 */
1534
1535 snprintf(uri, sizeof(uri), "/printers/%s", printer);
1536
1537 if ((response = cupsDoFileRequest(cups_server, request, uri,
1538 files[i])) != NULL)
1539 ippDelete(response);
1540 }
1541
1542 return (jobid);
1543 }
1544
1545
1546 /*
1547 * 'cups_connect()' - Connect to the specified host...
1548 */
1549
1550 static char * /* I - Printer name or NULL */
1551 cups_connect(const char *name, /* I - Destination (printer[@host]) */
1552 char *printer, /* O - Printer name [HTTP_MAX_URI] */
1553 char *hostname) /* O - Hostname [HTTP_MAX_URI] */
1554 {
1555 char hostbuf[HTTP_MAX_URI]; /* Name of host */
1556 static char printerbuf[HTTP_MAX_URI];
1557 /* Name of printer or class */
1558
1559
1560 DEBUG_printf(("cups_connect(\"%s\", %p, %p)\n", name, printer, hostname));
1561
1562 if (name == NULL)
1563 {
1564 last_error = IPP_BAD_REQUEST;
1565 return (NULL);
1566 }
1567
1568 if (sscanf(name, "%1023[^@]@%1023s", printerbuf, hostbuf) == 1)
1569 {
1570 strncpy(hostbuf, cupsServer(), sizeof(hostbuf) - 1);
1571 hostbuf[sizeof(hostbuf) - 1] = '\0';
1572 }
1573
1574 if (hostname != NULL)
1575 {
1576 strncpy(hostname, hostbuf, HTTP_MAX_URI - 1);
1577 hostname[HTTP_MAX_URI - 1] = '\0';
1578 }
1579 else
1580 hostname = hostbuf;
1581
1582 if (printer != NULL)
1583 {
1584 strncpy(printer, printerbuf, HTTP_MAX_URI - 1);
1585 printer[HTTP_MAX_URI - 1] = '\0';
1586 }
1587 else
1588 printer = printerbuf;
1589
1590 if (cups_server != NULL)
1591 {
1592 if (strcasecmp(cups_server->hostname, hostname) == 0)
1593 return (printer);
1594
1595 httpClose(cups_server);
1596 }
1597
1598 DEBUG_printf(("connecting to %s on port %d...\n", hostname, ippPort()));
1599
1600 if ((cups_server = httpConnectEncrypt(hostname, ippPort(),
1601 cupsEncryption())) == NULL)
1602 {
1603 last_error = IPP_SERVICE_UNAVAILABLE;
1604 return (NULL);
1605 }
1606 else
1607 return (printer);
1608 }
1609
1610
1611 /*
1612 * 'cups_local_auth()' - Get the local authorization certificate if
1613 * available/applicable...
1614 */
1615
1616 static int /* O - 1 if available, 0 if not */
1617 cups_local_auth(http_t *http) /* I - Connection */
1618 {
1619 #if defined(WIN32) || defined(__EMX__)
1620 /*
1621 * Currently WIN32 and OS-2 do not support the CUPS server...
1622 */
1623
1624 return (0);
1625 #else
1626 int pid; /* Current process ID */
1627 FILE *fp; /* Certificate file */
1628 char filename[1024], /* Certificate filename */
1629 certificate[33];/* Certificate string */
1630 const char *root; /* Server root directory */
1631
1632
1633 /*
1634 * See if we are accessing localhost...
1635 */
1636
1637 if (strcasecmp(http->hostname, "localhost") != 0)
1638 return (0);
1639
1640 if (!httpAddrLocalhost(&(http->hostaddr)))
1641 return (0);
1642
1643 /*
1644 * Try opening a certificate file for this PID. If that fails,
1645 * try the root certificate...
1646 */
1647
1648 if ((root = getenv("CUPS_SERVERROOT")) == NULL)
1649 root = CUPS_SERVERROOT;
1650
1651 pid = getpid();
1652 snprintf(filename, sizeof(filename), "%s/certs/%d", root, pid);
1653 if ((fp = fopen(filename, "r")) == NULL && pid > 0)
1654 {
1655 snprintf(filename, sizeof(filename), "%s/certs/0", root);
1656 fp = fopen(filename, "r");
1657 }
1658
1659 if (fp == NULL)
1660 return (0);
1661
1662 /*
1663 * Read the certificate from the file...
1664 */
1665
1666 fgets(certificate, sizeof(certificate), fp);
1667 fclose(fp);
1668
1669 /*
1670 * Set the authorization string and return...
1671 */
1672
1673 snprintf(authstring, sizeof(authstring), "Local %s", certificate);
1674
1675 return (1);
1676 #endif /* WIN32 || __EMX__ */
1677 }
1678
1679
1680 /*
1681 * End of "$Id: util.c,v 1.81.2.3 2001/12/26 16:52:13 mike Exp $".
1682 */