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