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