]> git.ipfire.org Git - thirdparty/cups.git/blob - cups/util.c
Update copyright notices, addresses, etc.
[thirdparty/cups.git] / cups / util.c
1 /*
2 * "$Id$"
3 *
4 * Printing utilities for the Common UNIX Printing System (CUPS).
5 *
6 * Copyright 1997-2005 by Easy Software Products.
7 *
8 * These coded instructions, statements, and computer programs are the
9 * property of Easy Software Products and are protected by Federal
10 * copyright law. Distribution and use rights are outlined in the file
11 * "LICENSE.txt" which should have been included with this file. If this
12 * file is missing or damaged please contact Easy Software Products
13 * at:
14 *
15 * Attn: CUPS Licensing Information
16 * Easy Software Products
17 * 44141 Airport View Drive, Suite 204
18 * Hollywood, Maryland 20636 USA
19 *
20 * Voice: (301) 373-9600
21 * EMail: cups-info@cups.org
22 * WWW: http://www.cups.org
23 *
24 * This file is subject to the Apple OS-Developed Software exception.
25 *
26 * Contents:
27 *
28 * cupsCancelJob() - Cancel a print job.
29 * cupsDoFileRequest() - Do an IPP request...
30 * cupsFreeJobs() - Free memory used by job data.
31 * cupsGetClasses() - Get a list of printer classes.
32 * cupsGetDefault() - Get the default printer or class.
33 * cupsGetDefault2() - Get the default printer or class.
34 * cupsGetJobs() - Get the jobs from the server.
35 * cupsGetJobs2() - Get the jobs from the server.
36 * cupsGetPPD() - Get the PPD file for a printer.
37 * cupsGetPPD2() - Get the PPD file for a printer.
38 * cupsGetPrinters() - Get a list of printers.
39 * cupsLastError() - Return the last IPP error that occurred.
40 * cupsPrintFile() - Print a file to a printer or class.
41 * cupsPrintFile2() - Print a file to a printer or class.
42 * cupsPrintFiles() - Print one or more files to a printer or class.
43 * cupsPrintFiles2() - Print one or more files to a printer or class.
44 * cups_connect() - Connect to the specified host...
45 */
46
47 /*
48 * Include necessary headers...
49 */
50
51 #include "cups.h"
52 #include "language.h"
53 #include "string.h"
54 #include "debug.h"
55 #include <stdlib.h>
56 #include <ctype.h>
57 #include <errno.h>
58 #include <fcntl.h>
59 #include <sys/stat.h>
60 #if defined(WIN32) || defined(__EMX__)
61 # include <io.h>
62 #else
63 # include <unistd.h>
64 #endif /* WIN32 || __EMX__ */
65
66
67 /*
68 * Local globals...
69 */
70
71 static http_t *cups_server = NULL; /* Current server connection */
72 static ipp_status_t last_error = IPP_OK; /* Last IPP error */
73
74
75 /*
76 * Local functions...
77 */
78
79 static char *cups_connect(const char *name, char *printer, char *hostname);
80
81
82 /*
83 * 'cupsCancelJob()' - Cancel a print job.
84 */
85
86 int /* O - 1 on success, 0 on failure */
87 cupsCancelJob(const char *name, /* I - Name of printer or class */
88 int job) /* I - Job ID */
89 {
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))
103 {
104 DEBUG_puts("Unable to connect to server!");
105 last_error = IPP_SERVICE_UNAVAILABLE;
106 return (0);
107 }
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
117 * [requesting-user-name]
118 */
119
120 request = ippNew();
121
122 request->request.op.operation_id = IPP_CANCEL_JOB;
123 request->request.op.request_id = 1;
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
134 cupsLangFree(language);
135
136 snprintf(uri, sizeof(uri), "ipp://%s:%d/printers/%s", hostname, ippPort(), printer);
137 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
138 NULL, uri);
139
140 ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_INTEGER, "job-id", job);
141
142 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
143 NULL, cupsUser());
144
145 /*
146 * Do the request...
147 */
148
149 if ((response = cupsDoRequest(cups_server, request, "/jobs/")) != NULL)
150 ippDelete(response);
151
152 return (last_error < IPP_REDIRECTION_OTHER_SITE);
153 }
154
155
156 /*
157 * 'cupsDoFileRequest()' - Do an IPP request...
158 */
159
160 ipp_t * /* O - Response data */
161 cupsDoFileRequest(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 */
165 {
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 */
172 char buffer[32768]; /* Output buffer */
173
174
175 DEBUG_printf(("cupsDoFileRequest(%p, %p, \'%s\', \'%s\')\n",
176 http, request, resource ? resource : "(null)",
177 filename ? filename : "(null)"));
178
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
188 /*
189 * See if we have a file to send...
190 */
191
192 if (filename != NULL)
193 {
194 if (stat(filename, &fileinfo))
195 {
196 /*
197 * Can't get file information!
198 */
199
200 ippDelete(request);
201 last_error = IPP_NOT_FOUND;
202 return (NULL);
203 }
204
205 #ifdef WIN32
206 if (fileinfo.st_mode & _S_IFDIR)
207 #else
208 if (S_ISDIR(fileinfo.st_mode))
209 #endif /* WIN32 */
210 {
211 /*
212 * Can't send a directory...
213 */
214
215 ippDelete(request);
216 last_error = IPP_NOT_POSSIBLE;
217 return (NULL);
218 }
219
220 if ((file = fopen(filename, "rb")) == NULL)
221 {
222 /*
223 * Can't open file!
224 */
225
226 ippDelete(request);
227 last_error = IPP_NOT_FOUND;
228 return (NULL);
229 }
230 }
231 else
232 file = NULL;
233
234 /*
235 * Loop until we can send the request without authorization problems.
236 */
237
238 response = NULL;
239 status = HTTP_ERROR;
240
241 while (response == NULL)
242 {
243 DEBUG_puts("cupsDoFileRequest: setup...");
244
245 /*
246 * Setup the HTTP variables needed...
247 */
248
249 if (filename != NULL)
250 sprintf(length, "%lu", (unsigned long)(ippLength(request) +
251 (size_t)fileinfo.st_size));
252 else
253 sprintf(length, "%lu", (unsigned long)ippLength(request));
254
255 httpClearFields(http);
256 httpSetField(http, HTTP_FIELD_CONTENT_LENGTH, length);
257 httpSetField(http, HTTP_FIELD_CONTENT_TYPE, "application/ipp");
258 httpSetField(http, HTTP_FIELD_AUTHORIZATION, http->authstring);
259
260 DEBUG_printf(("cupsDoFileRequest: authstring=\"%s\"\n", http->authstring));
261
262 /*
263 * Try the request...
264 */
265
266 DEBUG_puts("cupsDoFileRequest: post...");
267
268 if (httpPost(http, resource))
269 {
270 if (httpReconnect(http))
271 {
272 status = HTTP_ERROR;
273 break;
274 }
275 else
276 continue;
277 }
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;
286 status = HTTP_CONTINUE;
287
288 if (ippWrite(http, request) != IPP_ERROR)
289 if (filename != NULL)
290 {
291 DEBUG_puts("cupsDoFileRequest: file write...");
292
293 /*
294 * Send the file...
295 */
296
297 rewind(file);
298
299 while ((bytes = fread(buffer, 1, sizeof(buffer), file)) > 0)
300 {
301 if (httpCheck(http))
302 {
303 if ((status = httpUpdate(http)) != HTTP_CONTINUE)
304 break;
305 }
306
307 if (httpWrite(http, buffer, bytes) < bytes)
308 break;
309 }
310 }
311
312 /*
313 * Get the server's return status...
314 */
315
316 DEBUG_puts("cupsDoFileRequest: update...");
317
318 while (status == HTTP_CONTINUE)
319 status = httpUpdate(http);
320
321 DEBUG_printf(("cupsDoFileRequest: status = %d\n", status));
322
323 if (status == HTTP_UNAUTHORIZED)
324 {
325 DEBUG_puts("cupsDoFileRequest: unauthorized...");
326
327 /*
328 * Flush any error message...
329 */
330
331 httpFlush(http);
332
333 /*
334 * See if we can do authentication...
335 */
336
337 if (cupsDoAuthentication(http, "POST", resource))
338 break;
339
340 httpReconnect(http);
341
342 continue;
343 }
344 else if (status == HTTP_ERROR)
345 {
346 #ifdef WIN32
347 if (http->error != WSAENETDOWN && http->error != WSAENETUNREACH)
348 #else
349 if (http->error != ENETDOWN && http->error != ENETUNREACH)
350 #endif /* WIN32 */
351 continue;
352 else
353 break;
354 }
355 #ifdef HAVE_SSL
356 else if (status == HTTP_UPGRADE_REQUIRED)
357 {
358 /* Flush any error message... */
359 httpFlush(http);
360
361 /* Reconnect... */
362 httpReconnect(http);
363
364 /* Upgrade with encryption... */
365 httpEncryption(http, HTTP_ENCRYPT_REQUIRED);
366
367 /* Try again, this time with encryption enabled... */
368 continue;
369 }
370 #endif /* HAVE_SSL */
371 else if (status != HTTP_OK)
372 {
373 DEBUG_printf(("cupsDoFileRequest: error %d...\n", status));
374
375 /*
376 * Flush any error message...
377 */
378
379 httpFlush(http);
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
398 DEBUG_puts("IPP read error!");
399 ippDelete(response);
400 response = NULL;
401
402 last_error = IPP_SERVICE_UNAVAILABLE;
403 break;
404 }
405 }
406 }
407
408 /*
409 * Close the file if needed...
410 */
411
412 if (filename != NULL)
413 fclose(file);
414
415 /*
416 * Flush any remaining data...
417 */
418
419 httpFlush(http);
420
421 /*
422 * Delete the original request and return the response...
423 */
424
425 ippDelete(request);
426
427 if (response)
428 last_error = response->request.status.status_code;
429 else if (status != HTTP_OK)
430 {
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 }
467 }
468
469 return (response);
470 }
471
472
473 /*
474 * 'cupsFreeJobs()' - Free memory used by job data.
475 */
476
477 void
478 cupsFreeJobs(int num_jobs, /* I - Number of jobs */
479 cups_job_t *jobs) /* I - Jobs */
480 {
481 int i; /* Looping var */
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
499 /*
500 * 'cupsGetClasses()' - Get a list of printer classes.
501 */
502
503 int /* O - Number of classes */
504 cupsGetClasses(char ***classes) /* O - Classes */
505 {
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 */
512
513
514 if (classes == NULL)
515 {
516 last_error = IPP_INTERNAL_ERROR;
517 return (0);
518 }
519
520 /*
521 * Try to connect to the server...
522 */
523
524 if (!cups_connect("default", NULL, NULL))
525 {
526 DEBUG_puts("Unable to connect to server!");
527 last_error = IPP_SERVICE_UNAVAILABLE;
528 return (0);
529 }
530
531 /*
532 * Build a CUPS_GET_CLASSES request, which requires the following
533 * attributes:
534 *
535 * attributes-charset
536 * attributes-natural-language
537 * requested-attributes
538 */
539
540 request = ippNew();
541
542 request->request.op.operation_id = CUPS_GET_CLASSES;
543 request->request.op.request_id = 1;
544
545 language = cupsLangDefault();
546
547 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
548 "attributes-charset", NULL, cupsLangEncoding(language));
549
550 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
551 "attributes-natural-language", NULL, language->language);
552
553 cupsLangFree(language);
554
555 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
556 "requested-attributes", NULL, "printer-name");
557
558 /*
559 * Do the request and get back a response...
560 */
561
562 n = 0;
563 *classes = NULL;
564
565 if ((response = cupsDoRequest(cups_server, request, "/")) != NULL)
566 {
567 last_error = response->request.status.status_code;
568
569 for (attr = response->attrs; attr != NULL; attr = attr->next)
570 if (attr->name != NULL &&
571 strcasecmp(attr->name, "printer-name") == 0 &&
572 attr->value_tag == IPP_TAG_NAME)
573 {
574 if (n == 0)
575 temp = malloc(sizeof(char *));
576 else
577 temp = realloc(*classes, sizeof(char *) * (n + 1));
578
579 if (temp == NULL)
580 {
581 /*
582 * Ran out of memory!
583 */
584
585 while (n > 0)
586 {
587 n --;
588 free((*classes)[n]);
589 }
590
591 free(*classes);
592 ippDelete(response);
593 return (0);
594 }
595
596 *classes = temp;
597 temp[n] = strdup(attr->values[0].string.text);
598 n ++;
599 }
600
601 ippDelete(response);
602 }
603 else
604 last_error = IPP_BAD_REQUEST;
605
606 return (n);
607 }
608
609
610 /*
611 * 'cupsGetDefault()' - Get the default printer or class.
612 */
613
614 const char * /* O - Default printer or NULL */
615 cupsGetDefault(void)
616 {
617 const char *var; /* Environment variable */
618
619
620 /*
621 * First see if the LPDEST or PRINTER environment variables are
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"...
625 */
626
627 if ((var = getenv("LPDEST")) != NULL)
628 return (var);
629 else if ((var = getenv("PRINTER")) != NULL && strcmp(var, "lp") != 0)
630 return (var);
631
632 /*
633 * Try to connect to the server...
634 */
635
636 if (!cups_connect("default", NULL, NULL))
637 {
638 DEBUG_puts("Unable to connect to server!");
639 last_error = IPP_SERVICE_UNAVAILABLE;
640 return (NULL);
641 }
642
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
655 const char * /* O - Default printer or NULL */
656 cupsGetDefault2(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
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
695 request->request.op.operation_id = CUPS_GET_DEFAULT;
696 request->request.op.request_id = 1;
697
698 language = cupsLangDefault();
699
700 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
701 "attributes-charset", NULL, cupsLangEncoding(language));
702
703 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
704 "attributes-natural-language", NULL, language->language);
705
706 cupsLangFree(language);
707
708 /*
709 * Do the request and get back a response...
710 */
711
712 if ((response = cupsDoRequest(http, request, "/")) != NULL)
713 {
714 last_error = response->request.status.status_code;
715
716 if ((attr = ippFindAttribute(response, "printer-name", IPP_TAG_NAME)) != NULL)
717 {
718 strlcpy(def_printer, attr->values[0].string.text, sizeof(def_printer));
719 ippDelete(response);
720 return (def_printer);
721 }
722
723 ippDelete(response);
724 }
725 else
726 last_error = IPP_BAD_REQUEST;
727
728 return (NULL);
729 }
730
731
732 /*
733 * 'cupsGetJobs()' - Get the jobs from the server.
734 */
735
736 int /* O - Number of jobs */
737 cupsGetJobs(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? */
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
766 int /* O - Number of jobs */
767 cupsGetJobs2(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? */
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 */
791 static const char * const attrs[] = /* Requested attributes */
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
807 if (!http || !jobs)
808 {
809 last_error = IPP_INTERNAL_ERROR;
810 return (-1);
811 }
812
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
828 request->request.op.operation_id = IPP_GET_JOBS;
829 request->request.op.request_id = 1;
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
839 cupsLangFree(language);
840
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
870 if ((response = cupsDoRequest(http, request, "/")) != NULL)
871 {
872 last_error = response->request.status.status_code;
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;
894 user = "unknown";
895 dest = NULL;
896 format = "application/octet-stream";
897 title = "untitled";
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 &&
938 (attr->value_tag == IPP_TAG_TEXT ||
939 attr->value_tag == IPP_TAG_NAME))
940 title = attr->values[0].string.text;
941
942 attr = attr->next;
943 }
944
945 /*
946 * See if we have everything needed...
947 */
948
949 if (dest == NULL || id == 0)
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;
998
999 if (attr == NULL)
1000 break;
1001 }
1002
1003 ippDelete(response);
1004 }
1005 else
1006 last_error = IPP_BAD_REQUEST;
1007
1008 if (n == 0 && last_error >= IPP_BAD_REQUEST)
1009 return (-1);
1010 else
1011 return (n);
1012 }
1013
1014
1015 /*
1016 * 'cupsGetPPD()' - Get the PPD file for a printer.
1017 */
1018
1019 const char * /* O - Filename for PPD file */
1020 cupsGetPPD(const char *name) /* I - Printer name */
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
1045 const char * /* O - Filename for PPD file */
1046 cupsGetPPD2(http_t *http, /* I - HTTP connection */
1047 const char *name) /* I - Printer name */
1048 {
1049 int i; /* Looping var */
1050 http_t *http2; /* Alternate HTTP connection */
1051 ipp_t *request, /* IPP request */
1052 *response; /* IPP response */
1053 ipp_attribute_t *attr; /* Current attribute */
1054 cups_lang_t *language; /* Local language */
1055 int fd; /* PPD file */
1056 char uri[HTTP_MAX_URI], /* Printer URI */
1057 printer[HTTP_MAX_URI], /* Printer name */
1058 method[HTTP_MAX_URI], /* Method/scheme name */
1059 username[HTTP_MAX_URI], /* Username:password */
1060 hostname[HTTP_MAX_URI], /* Hostname */
1061 resource[HTTP_MAX_URI]; /* Resource name */
1062 int port; /* Port number */
1063 http_status_t status; /* HTTP status from server */
1064 static char filename[HTTP_MAX_URI]; /* Local filename */
1065 static const char * const requested_attrs[] =
1066 { /* Requested attributes */
1067 "printer-uri-supported",
1068 "printer-type",
1069 "member-uris"
1070 };
1071
1072
1073 /*
1074 * Range check input...
1075 */
1076
1077 DEBUG_printf(("cupsGetPPD2(http=%p, name=\"%s\")\n", http,
1078 name ? name : "(null)"));
1079
1080 if (!http || !name)
1081 {
1082 last_error = IPP_INTERNAL_ERROR;
1083 return (NULL);
1084 }
1085
1086 /*
1087 * Build an IPP_GET_PRINTER_ATTRIBUTES request, which requires the following
1088 * attributes:
1089 *
1090 * attributes-charset
1091 * attributes-natural-language
1092 * printer-uri
1093 * requested-attributes
1094 */
1095
1096 request = ippNew();
1097
1098 request->request.op.operation_id = IPP_GET_PRINTER_ATTRIBUTES;
1099 request->request.op.request_id = 1;
1100
1101 language = cupsLangDefault();
1102
1103 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
1104 "attributes-charset", NULL, cupsLangEncoding(language));
1105
1106 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
1107 "attributes-natural-language", NULL, language->language);
1108
1109 cupsLangFree(language);
1110
1111 snprintf(uri, sizeof(uri), "ipp://localhost/printers/%s", name);
1112 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
1113 "printer-uri", NULL, uri);
1114
1115 DEBUG_printf(("cupsGetPPD2: printer-uri=\"%s\"\n", uri));
1116
1117 ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
1118 "requested-attributes",
1119 sizeof(requested_attrs) / sizeof(requested_attrs[0]),
1120 NULL, requested_attrs);
1121
1122 /*
1123 * Do the request and get back a response...
1124 */
1125
1126 if ((response = cupsDoRequest(http, request, "/")) != NULL)
1127 {
1128 last_error = response->request.status.status_code;
1129 printer[0] = '\0';
1130 hostname[0] = '\0';
1131
1132 if ((attr = ippFindAttribute(response, "member-uris", IPP_TAG_URI)) != NULL)
1133 {
1134 /*
1135 * Get the first actual server and printer name in the class...
1136 */
1137
1138 for (i = 0; i < attr->num_values; i ++)
1139 {
1140 httpSeparate(attr->values[0].string.text, method, username, hostname,
1141 &port, resource);
1142 if (strncmp(resource, "/printers/", 10) == 0)
1143 {
1144 /*
1145 * Found a printer!
1146 */
1147
1148 strlcpy(printer, resource + 10, sizeof(printer));
1149 break;
1150 }
1151 }
1152 }
1153 else if ((attr = ippFindAttribute(response, "printer-uri-supported",
1154 IPP_TAG_URI)) != NULL)
1155 {
1156 /*
1157 * Get the actual server and printer names...
1158 */
1159
1160 httpSeparate(attr->values[0].string.text, method, username, hostname,
1161 &port, resource);
1162 strlcpy(printer, strrchr(resource, '/') + 1, sizeof(printer));
1163 }
1164
1165 ippDelete(response);
1166
1167 /*
1168 * Remap local hostname to localhost...
1169 */
1170
1171 gethostname(uri, sizeof(uri));
1172
1173 if (strcasecmp(uri, hostname) == 0)
1174 strcpy(hostname, "localhost");
1175 }
1176
1177 if (!printer[0])
1178 {
1179 last_error = IPP_NOT_FOUND;
1180 return (NULL);
1181 }
1182
1183 /*
1184 * Reconnect to the correct server as needed...
1185 */
1186
1187 if (!strcasecmp(http->hostname, hostname))
1188 http2 = http;
1189 else if ((http2 = httpConnectEncrypt(hostname, ippPort(),
1190 cupsEncryption())) == NULL)
1191 {
1192 DEBUG_puts("Unable to connect to server!");
1193 last_error = IPP_SERVICE_UNAVAILABLE;
1194 return (NULL);
1195 }
1196
1197 /*
1198 * Get a temp file...
1199 */
1200
1201 if ((fd = cupsTempFd(filename, sizeof(filename))) < 0)
1202 {
1203 /*
1204 * Can't open file; close the server connection and return NULL...
1205 */
1206
1207 last_error = IPP_INTERNAL_ERROR;
1208
1209 if (http2 != http)
1210 httpClose(http2);
1211
1212 return (NULL);
1213 }
1214
1215 /*
1216 * And send a request to the HTTP server...
1217 */
1218
1219 snprintf(resource, sizeof(resource), "/printers/%s.ppd", printer);
1220
1221 status = cupsGetFd(http2, resource, fd);
1222
1223 close(fd);
1224
1225 if (http2 != http)
1226 httpClose(http2);
1227
1228 /*
1229 * See if we actually got the file or an error...
1230 */
1231
1232 if (status != HTTP_OK)
1233 {
1234 switch (status)
1235 {
1236 case HTTP_NOT_FOUND :
1237 last_error = IPP_NOT_FOUND;
1238 break;
1239 case HTTP_ERROR :
1240 DEBUG_puts("Mapping HTTP error to IPP_ERROR");
1241 last_error = IPP_ERROR;
1242 break;
1243 case HTTP_UNAUTHORIZED :
1244 last_error = IPP_NOT_AUTHORIZED;
1245 break;
1246 default :
1247 last_error = IPP_INTERNAL_ERROR;
1248 break;
1249 }
1250
1251 unlink(filename);
1252
1253 return (NULL);
1254 }
1255
1256 /*
1257 * Return the PPD file...
1258 */
1259
1260 return (filename);
1261 }
1262
1263
1264 /*
1265 * 'cupsGetPrinters()' - Get a list of printers.
1266 */
1267
1268 int /* O - Number of printers */
1269 cupsGetPrinters(char ***printers) /* O - Printers */
1270 {
1271 int n; /* Number of printers */
1272 ipp_t *request, /* IPP Request */
1273 *response; /* IPP Response */
1274 ipp_attribute_t *attr; /* Current attribute */
1275 cups_lang_t *language; /* Default language */
1276 char **temp; /* Temporary pointer */
1277
1278
1279 if (printers == NULL)
1280 {
1281 last_error = IPP_INTERNAL_ERROR;
1282 return (0);
1283 }
1284
1285 /*
1286 * Try to connect to the server...
1287 */
1288
1289 if (!cups_connect("default", NULL, NULL))
1290 {
1291 DEBUG_puts("Unable to connect to server!");
1292 last_error = IPP_SERVICE_UNAVAILABLE;
1293 return (0);
1294 }
1295
1296 /*
1297 * Build a CUPS_GET_PRINTERS request, which requires the following
1298 * attributes:
1299 *
1300 * attributes-charset
1301 * attributes-natural-language
1302 * requested-attributes
1303 */
1304
1305 request = ippNew();
1306
1307 request->request.op.operation_id = CUPS_GET_PRINTERS;
1308 request->request.op.request_id = 1;
1309
1310 language = cupsLangDefault();
1311
1312 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
1313 "attributes-charset", NULL, cupsLangEncoding(language));
1314
1315 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
1316 "attributes-natural-language", NULL, language->language);
1317
1318 cupsLangFree(language);
1319
1320 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
1321 "requested-attributes", NULL, "printer-name");
1322
1323 /*
1324 * Do the request and get back a response...
1325 */
1326
1327 n = 0;
1328 *printers = NULL;
1329
1330 if ((response = cupsDoRequest(cups_server, request, "/")) != NULL)
1331 {
1332 last_error = response->request.status.status_code;
1333
1334 for (attr = response->attrs; attr != NULL; attr = attr->next)
1335 if (attr->name != NULL &&
1336 strcasecmp(attr->name, "printer-name") == 0 &&
1337 attr->value_tag == IPP_TAG_NAME)
1338 {
1339 if (n == 0)
1340 temp = malloc(sizeof(char *));
1341 else
1342 temp = realloc(*printers, sizeof(char *) * (n + 1));
1343
1344 if (temp == NULL)
1345 {
1346 /*
1347 * Ran out of memory!
1348 */
1349
1350 while (n > 0)
1351 {
1352 n --;
1353 free((*printers)[n]);
1354 }
1355
1356 free(*printers);
1357 ippDelete(response);
1358 return (0);
1359 }
1360
1361 *printers = temp;
1362 temp[n] = strdup(attr->values[0].string.text);
1363 n ++;
1364 }
1365
1366 ippDelete(response);
1367 }
1368 else
1369 last_error = IPP_BAD_REQUEST;
1370
1371 return (n);
1372 }
1373
1374
1375 /*
1376 * 'cupsLastError()' - Return the last IPP error that occurred.
1377 */
1378
1379 ipp_status_t /* O - IPP error code */
1380 cupsLastError(void)
1381 {
1382 return (last_error);
1383 }
1384
1385 /*
1386 * 'cupsPrintFile()' - Print a file to a printer or class.
1387 */
1388
1389 int /* O - Job ID */
1390 cupsPrintFile(const char *name, /* I - Printer or class name */
1391 const char *filename, /* I - File to print */
1392 const char *title, /* I - Title of job */
1393 int num_options,/* I - Number of options */
1394 cups_option_t *options) /* I - Options */
1395 {
1396 DEBUG_printf(("cupsPrintFile(name=\"%s\", filename=\"%s\", "
1397 "title=\"%s\", num_options=%d, options=%p)\n",
1398 name, filename, title, num_options, options));
1399
1400 return (cupsPrintFiles(name, 1, &filename, title, num_options, options));
1401 }
1402
1403
1404 /*
1405 * 'cupsPrintFile2()' - Print a file to a printer or class.
1406 */
1407
1408 int /* O - Job ID */
1409 cupsPrintFile2(http_t *http, /* I - HTTP connection */
1410 const char *name, /* I - Printer or class name */
1411 const char *filename, /* I - File to print */
1412 const char *title, /* I - Title of job */
1413 int num_options,
1414 /* I - Number of options */
1415 cups_option_t *options) /* I - Options */
1416 {
1417 DEBUG_printf(("cupsPrintFile2(http=%p, name=\"%s\", filename=\"%s\", "
1418 "title=\"%s\", num_options=%d, options=%p)\n",
1419 http, name, filename, title, num_options, options));
1420
1421 return (cupsPrintFiles2(http, name, 1, &filename, title, num_options, options));
1422 }
1423
1424
1425 /*
1426 * 'cupsPrintFiles()' - Print one or more files to a printer or class.
1427 */
1428
1429 int /* O - Job ID */
1430 cupsPrintFiles(const char *name, /* I - Printer or class name */
1431 int num_files, /* I - Number of files */
1432 const char **files, /* I - File(s) to print */
1433 const char *title, /* I - Title of job */
1434 int num_options,
1435 /* I - Number of options */
1436 cups_option_t *options) /* I - Options */
1437 {
1438 DEBUG_printf(("cupsPrintFiles(name=\"%s\", num_files=%d, "
1439 "files=%p, title=\"%s\", num_options=%d, options=%p)\n",
1440 name, num_files, files, title, num_options, options));
1441
1442
1443 /*
1444 * Setup a connection and request data...
1445 */
1446
1447 if (!cups_connect(name, NULL, NULL))
1448 {
1449 DEBUG_printf(("cupsPrintFiles: Unable to open connection - %s.\n",
1450 strerror(errno)));
1451 DEBUG_puts("Unable to connect to server!");
1452 last_error = IPP_SERVICE_UNAVAILABLE;
1453 return (0);
1454 }
1455
1456 /*
1457 * Print the file(s)...
1458 */
1459
1460 return (cupsPrintFiles2(cups_server, name, num_files, files, title,
1461 num_options, options));
1462 }
1463
1464
1465
1466 /*
1467 * 'cupsPrintFiles2()' - Print one or more files to a printer or class.
1468 */
1469
1470 int /* O - Job ID */
1471 cupsPrintFiles2(http_t *http, /* I - HTTP connection */
1472 const char *name, /* I - Printer or class name */
1473 int num_files,/* I - Number of files */
1474 const char **files, /* I - File(s) to print */
1475 const char *title, /* I - Title of job */
1476 int num_options,
1477 /* I - Number of options */
1478 cups_option_t *options) /* I - Options */
1479 {
1480 int i; /* Looping var */
1481 const char *val; /* Pointer to option value */
1482 ipp_t *request; /* IPP request */
1483 ipp_t *response; /* IPP response */
1484 ipp_attribute_t *attr; /* IPP job-id attribute */
1485 char uri[HTTP_MAX_URI]; /* Printer URI */
1486 cups_lang_t *language; /* Language to use */
1487 int jobid; /* New job ID */
1488
1489
1490 DEBUG_printf(("cupsPrintFiles(http=%p, name=\"%s\", num_files=%d, "
1491 "files=%p, title=\"%s\", num_options=%d, options=%p)\n",
1492 http, name, num_files, files, title, num_options, options));
1493
1494 /*
1495 * Range check input...
1496 */
1497
1498 if (!http || !name || num_files < 1 || files == NULL)
1499 return (0);
1500
1501 /*
1502 * Setup the request data...
1503 */
1504
1505 language = cupsLangDefault();
1506
1507 /*
1508 * Build a standard CUPS URI for the printer and fill the standard IPP
1509 * attributes...
1510 */
1511
1512 if ((request = ippNew()) == NULL)
1513 return (0);
1514
1515 request->request.op.operation_id = num_files == 1 ? IPP_PRINT_JOB :
1516 IPP_CREATE_JOB;
1517 request->request.op.request_id = 1;
1518
1519 snprintf(uri, sizeof(uri), "ipp://%s:%d/printers/%s", http->hostname,
1520 ippPort(), name);
1521
1522 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
1523 "attributes-charset", NULL, cupsLangEncoding(language));
1524
1525 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
1526 "attributes-natural-language", NULL,
1527 language != NULL ? language->language : "C");
1528
1529 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
1530 NULL, uri);
1531
1532 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
1533 NULL, cupsUser());
1534
1535 if (title)
1536 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "job-name", NULL,
1537 title);
1538
1539 /*
1540 * Then add all options...
1541 */
1542
1543 cupsEncodeOptions(request, num_options, options);
1544
1545 /*
1546 * Do the request...
1547 */
1548
1549 snprintf(uri, sizeof(uri), "/printers/%s", name);
1550
1551 if (num_files == 1)
1552 response = cupsDoFileRequest(http, request, uri, *files);
1553 else
1554 response = cupsDoRequest(http, request, uri);
1555
1556 if (response == NULL)
1557 jobid = 0;
1558 else if (response->request.status.status_code > IPP_OK_CONFLICT)
1559 {
1560 DEBUG_printf(("IPP response code was 0x%x!\n",
1561 response->request.status.status_code));
1562 jobid = 0;
1563 }
1564 else if ((attr = ippFindAttribute(response, "job-id", IPP_TAG_INTEGER)) == NULL)
1565 {
1566 DEBUG_puts("No job ID!");
1567
1568 last_error = IPP_SERVICE_UNAVAILABLE;
1569
1570 jobid = 0;
1571 }
1572 else
1573 jobid = attr->values[0].integer;
1574
1575 if (response != NULL)
1576 ippDelete(response);
1577
1578 /*
1579 * Handle multiple file jobs if the create-job operation worked...
1580 */
1581
1582 if (jobid > 0 && num_files > 1)
1583 for (i = 0; i < num_files; i ++)
1584 {
1585 /*
1586 * Build a standard CUPS URI for the job and fill the standard IPP
1587 * attributes...
1588 */
1589
1590 if ((request = ippNew()) == NULL)
1591 return (0);
1592
1593 request->request.op.operation_id = IPP_SEND_DOCUMENT;
1594 request->request.op.request_id = 1;
1595
1596 snprintf(uri, sizeof(uri), "ipp://%s:%d/jobs/%d", http->hostname,
1597 ippPort(), jobid);
1598
1599 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
1600 "attributes-charset", NULL, cupsLangEncoding(language));
1601
1602 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
1603 "attributes-natural-language", NULL,
1604 language != NULL ? language->language : "C");
1605
1606 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri",
1607 NULL, uri);
1608
1609 /*
1610 * Handle raw print files...
1611 */
1612
1613 if (cupsGetOption("raw", num_options, options))
1614 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_MIMETYPE, "document-format",
1615 NULL, "application/vnd.cups-raw");
1616 else if ((val = cupsGetOption("document-format", num_options, options)) != NULL)
1617 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_MIMETYPE, "document-format",
1618 NULL, val);
1619 else
1620 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_MIMETYPE, "document-format",
1621 NULL, "application/octet-stream");
1622
1623 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
1624 NULL, cupsUser());
1625
1626 /*
1627 * Is this the last document?
1628 */
1629
1630 if (i == (num_files - 1))
1631 ippAddBoolean(request, IPP_TAG_OPERATION, "last-document", 1);
1632
1633 /*
1634 * Send the file...
1635 */
1636
1637 snprintf(uri, sizeof(uri), "/printers/%s", name);
1638
1639 if ((response = cupsDoFileRequest(http, request, uri,
1640 files[i])) != NULL)
1641 ippDelete(response);
1642 }
1643
1644 cupsLangFree(language);
1645
1646 return (jobid);
1647 }
1648
1649
1650 /*
1651 * 'cups_connect()' - Connect to the specified host...
1652 */
1653
1654 static char * /* I - Printer name or NULL */
1655 cups_connect(const char *name, /* I - Destination (printer[@host]) */
1656 char *printer, /* O - Printer name [HTTP_MAX_URI] */
1657 char *hostname) /* O - Hostname [HTTP_MAX_URI] */
1658 {
1659 char hostbuf[HTTP_MAX_URI]; /* Name of host */
1660
1661
1662 DEBUG_printf(("cups_connect(\"%s\", %p, %p)\n", name, printer, hostname));
1663
1664 if (name == NULL)
1665 {
1666 last_error = IPP_BAD_REQUEST;
1667 return (NULL);
1668 }
1669
1670 /*
1671 * All jobs are now queued to cupsServer() to avoid hostname
1672 * resolution problems and to ensure that the user sees all
1673 * locally queued jobs locally.
1674 */
1675
1676 strlcpy(hostbuf, cupsServer(), sizeof(hostbuf));
1677
1678 if (hostname != NULL)
1679 strlcpy(hostname, hostbuf, HTTP_MAX_URI);
1680 else
1681 hostname = hostbuf;
1682
1683 if (printer != NULL)
1684 strlcpy(printer, name, HTTP_MAX_URI);
1685 else
1686 printer = (char *)name;
1687
1688 if (cups_server != NULL)
1689 {
1690 if (strcasecmp(cups_server->hostname, hostname) == 0)
1691 return (printer);
1692
1693 httpClose(cups_server);
1694 }
1695
1696 DEBUG_printf(("connecting to %s on port %d...\n", hostname, ippPort()));
1697
1698 if ((cups_server = httpConnectEncrypt(hostname, ippPort(),
1699 cupsEncryption())) == NULL)
1700 {
1701 DEBUG_puts("Unable to connect to server!");
1702 last_error = IPP_SERVICE_UNAVAILABLE;
1703 return (NULL);
1704 }
1705 else
1706 return (printer);
1707 }
1708
1709
1710 /*
1711 * End of "$Id$".
1712 */