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