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