s3: Lift the smbd_messaging_context from check_published_printers
[Samba/gbeck.git] / source3 / printing / print_cups.c
blobcbefa07a3363a6ba1ed1d15e63fbdf2b2a558e4e
1 /*
2 * Support code for the Common UNIX Printing System ("CUPS")
4 * Copyright 1999-2003 by Michael R Sweet.
5 * Copyright 2008 Jeremy Allison.
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, see <http://www.gnu.org/licenses/>.
22 * JRA. Converted to utf8 pull/push.
25 #include "includes.h"
26 #include "printing.h"
27 #include "printing/pcap.h"
29 #ifdef HAVE_CUPS
30 #include <cups/cups.h>
31 #include <cups/language.h>
33 static SIG_ATOMIC_T gotalarm;
35 /***************************************************************
36 Signal function to tell us we timed out.
37 ****************************************************************/
39 static void gotalarm_sig(int signum)
41 gotalarm = 1;
44 extern userdom_struct current_user_info;
47 * 'cups_passwd_cb()' - The CUPS password callback...
50 static const char * /* O - Password or NULL */
51 cups_passwd_cb(const char *prompt) /* I - Prompt */
54 * Always return NULL to indicate that no password is available...
57 return (NULL);
60 static http_t *cups_connect(TALLOC_CTX *frame)
62 http_t *http = NULL;
63 char *server = NULL, *p = NULL;
64 int port;
65 int timeout = lp_cups_connection_timeout();
66 size_t size;
68 if (lp_cups_server() != NULL && strlen(lp_cups_server()) > 0) {
69 if (!push_utf8_talloc(frame, &server, lp_cups_server(), &size)) {
70 return NULL;
72 } else {
73 server = talloc_strdup(frame,cupsServer());
75 if (!server) {
76 return NULL;
79 p = strchr(server, ':');
80 if (p) {
81 port = atoi(p+1);
82 *p = '\0';
83 } else {
84 port = ippPort();
87 DEBUG(10, ("connecting to cups server %s:%d\n",
88 server, port));
90 gotalarm = 0;
92 if (timeout) {
93 CatchSignal(SIGALRM, gotalarm_sig);
94 alarm(timeout);
97 #ifdef HAVE_HTTPCONNECTENCRYPT
98 http = httpConnectEncrypt(server, port, lp_cups_encrypt());
99 #else
100 http = httpConnect(server, port);
101 #endif
104 CatchSignal(SIGALRM, SIG_IGN);
105 alarm(0);
107 if (http == NULL) {
108 DEBUG(0,("Unable to connect to CUPS server %s:%d - %s\n",
109 server, port, strerror(errno)));
112 return http;
115 static void send_pcap_info(const char *name, const char *info, void *pd)
117 int fd = *(int *)pd;
118 size_t namelen = name ? strlen(name)+1 : 0;
119 size_t infolen = info ? strlen(info)+1 : 0;
121 DEBUG(11,("send_pcap_info: writing namelen %u\n", (unsigned int)namelen));
122 if (sys_write(fd, &namelen, sizeof(namelen)) != sizeof(namelen)) {
123 DEBUG(10,("send_pcap_info: namelen write failed %s\n",
124 strerror(errno)));
125 return;
127 DEBUG(11,("send_pcap_info: writing infolen %u\n", (unsigned int)infolen));
128 if (sys_write(fd, &infolen, sizeof(infolen)) != sizeof(infolen)) {
129 DEBUG(10,("send_pcap_info: infolen write failed %s\n",
130 strerror(errno)));
131 return;
133 if (namelen) {
134 DEBUG(11,("send_pcap_info: writing name %s\n", name));
135 if (sys_write(fd, name, namelen) != namelen) {
136 DEBUG(10,("send_pcap_info: name write failed %s\n",
137 strerror(errno)));
138 return;
141 if (infolen) {
142 DEBUG(11,("send_pcap_info: writing info %s\n", info));
143 if (sys_write(fd, info, infolen) != infolen) {
144 DEBUG(10,("send_pcap_info: info write failed %s\n",
145 strerror(errno)));
146 return;
151 static bool cups_cache_reload_async(int fd)
153 TALLOC_CTX *frame = talloc_stackframe();
154 struct pcap_cache *tmp_pcap_cache = NULL;
155 http_t *http = NULL; /* HTTP connection to server */
156 ipp_t *request = NULL, /* IPP Request */
157 *response = NULL; /* IPP Response */
158 ipp_attribute_t *attr; /* Current attribute */
159 cups_lang_t *language = NULL; /* Default language */
160 char *name, /* printer-name attribute */
161 *info; /* printer-info attribute */
162 static const char *requested[] =/* Requested attributes */
164 "printer-name",
165 "printer-info"
167 bool ret = False;
168 size_t size;
170 DEBUG(5, ("reloading cups printcap cache\n"));
173 * Make sure we don't ask for passwords...
176 cupsSetPasswordCB(cups_passwd_cb);
179 * Try to connect to the server...
182 if ((http = cups_connect(frame)) == NULL) {
183 goto out;
187 * Build a CUPS_GET_PRINTERS request, which requires the following
188 * attributes:
190 * attributes-charset
191 * attributes-natural-language
192 * requested-attributes
195 request = ippNew();
197 request->request.op.operation_id = CUPS_GET_PRINTERS;
198 request->request.op.request_id = 1;
200 language = cupsLangDefault();
202 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
203 "attributes-charset", NULL, "utf-8");
205 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
206 "attributes-natural-language", NULL, language->language);
208 ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
209 "requested-attributes",
210 (sizeof(requested) / sizeof(requested[0])),
211 NULL, requested);
214 * Do the request and get back a response...
217 if ((response = cupsDoRequest(http, request, "/")) == NULL) {
218 DEBUG(0,("Unable to get printer list - %s\n",
219 ippErrorString(cupsLastError())));
220 goto out;
223 for (attr = response->attrs; attr != NULL;) {
225 * Skip leading attributes until we hit a printer...
228 while (attr != NULL && attr->group_tag != IPP_TAG_PRINTER)
229 attr = attr->next;
231 if (attr == NULL)
232 break;
235 * Pull the needed attributes from this printer...
238 name = NULL;
239 info = NULL;
241 while (attr != NULL && attr->group_tag == IPP_TAG_PRINTER) {
242 if (strcmp(attr->name, "printer-name") == 0 &&
243 attr->value_tag == IPP_TAG_NAME) {
244 if (!pull_utf8_talloc(frame,
245 &name,
246 attr->values[0].string.text,
247 &size)) {
248 goto out;
252 if (strcmp(attr->name, "printer-info") == 0 &&
253 attr->value_tag == IPP_TAG_TEXT) {
254 if (!pull_utf8_talloc(frame,
255 &info,
256 attr->values[0].string.text,
257 &size)) {
258 goto out;
262 attr = attr->next;
266 * See if we have everything needed...
269 if (name == NULL)
270 break;
272 if (!pcap_cache_add_specific(&tmp_pcap_cache, name, info)) {
273 goto out;
277 ippDelete(response);
278 response = NULL;
281 * Build a CUPS_GET_CLASSES request, which requires the following
282 * attributes:
284 * attributes-charset
285 * attributes-natural-language
286 * requested-attributes
289 request = ippNew();
291 request->request.op.operation_id = CUPS_GET_CLASSES;
292 request->request.op.request_id = 1;
294 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
295 "attributes-charset", NULL, "utf-8");
297 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
298 "attributes-natural-language", NULL, language->language);
300 ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
301 "requested-attributes",
302 (sizeof(requested) / sizeof(requested[0])),
303 NULL, requested);
306 * Do the request and get back a response...
309 if ((response = cupsDoRequest(http, request, "/")) == NULL) {
310 DEBUG(0,("Unable to get printer list - %s\n",
311 ippErrorString(cupsLastError())));
312 goto out;
315 for (attr = response->attrs; attr != NULL;) {
317 * Skip leading attributes until we hit a printer...
320 while (attr != NULL && attr->group_tag != IPP_TAG_PRINTER)
321 attr = attr->next;
323 if (attr == NULL)
324 break;
327 * Pull the needed attributes from this printer...
330 name = NULL;
331 info = NULL;
333 while (attr != NULL && attr->group_tag == IPP_TAG_PRINTER) {
334 if (strcmp(attr->name, "printer-name") == 0 &&
335 attr->value_tag == IPP_TAG_NAME) {
336 if (!pull_utf8_talloc(frame,
337 &name,
338 attr->values[0].string.text,
339 &size)) {
340 goto out;
344 if (strcmp(attr->name, "printer-info") == 0 &&
345 attr->value_tag == IPP_TAG_TEXT) {
346 if (!pull_utf8_talloc(frame,
347 &info,
348 attr->values[0].string.text,
349 &size)) {
350 goto out;
354 attr = attr->next;
358 * See if we have everything needed...
361 if (name == NULL)
362 break;
364 if (!pcap_cache_add_specific(&tmp_pcap_cache, name, info)) {
365 goto out;
369 ret = True;
371 out:
372 if (response)
373 ippDelete(response);
375 if (language)
376 cupsLangFree(language);
378 if (http)
379 httpClose(http);
381 /* Send all the entries up the pipe. */
382 if (tmp_pcap_cache) {
383 pcap_printer_fn_specific(tmp_pcap_cache,
384 send_pcap_info,
385 (void *)&fd);
387 pcap_cache_destroy_specific(&tmp_pcap_cache);
389 TALLOC_FREE(frame);
390 return ret;
393 static struct pcap_cache *local_pcap_copy;
394 struct fd_event *cache_fd_event;
396 static bool cups_pcap_load_async(int *pfd)
398 int fds[2];
399 pid_t pid;
400 NTSTATUS status;
402 *pfd = -1;
404 if (cache_fd_event) {
405 DEBUG(3,("cups_pcap_load_async: already waiting for "
406 "a refresh event\n" ));
407 return false;
410 DEBUG(5,("cups_pcap_load_async: asynchronously loading cups printers\n"));
412 if (pipe(fds) == -1) {
413 return false;
416 pid = sys_fork();
417 if (pid == (pid_t)-1) {
418 DEBUG(10,("cups_pcap_load_async: fork failed %s\n",
419 strerror(errno) ));
420 close(fds[0]);
421 close(fds[1]);
422 return false;
425 if (pid) {
426 DEBUG(10,("cups_pcap_load_async: child pid = %u\n",
427 (unsigned int)pid ));
428 /* Parent. */
429 close(fds[1]);
430 *pfd = fds[0];
431 return true;
434 /* Child. */
436 close_all_print_db();
438 status = reinit_after_fork(server_messaging_context(),
439 server_event_context(), procid_self(),
440 true);
441 if (!NT_STATUS_IS_OK(status)) {
442 DEBUG(0,("cups_pcap_load_async: reinit_after_fork() failed\n"));
443 smb_panic("cups_pcap_load_async: reinit_after_fork() failed");
446 close(fds[0]);
447 cups_cache_reload_async(fds[1]);
448 close(fds[1]);
449 _exit(0);
452 static void cups_async_callback(struct event_context *event_ctx,
453 struct fd_event *event,
454 uint16 flags,
455 void *p)
457 TALLOC_CTX *frame = talloc_stackframe();
458 int fd = *(int *)p;
459 struct pcap_cache *tmp_pcap_cache = NULL;
461 DEBUG(5,("cups_async_callback: callback received for printer data. "
462 "fd = %d\n", fd));
464 while (1) {
465 char *name = NULL, *info = NULL;
466 size_t namelen = 0, infolen = 0;
467 ssize_t ret = -1;
469 ret = sys_read(fd, &namelen, sizeof(namelen));
470 if (ret == 0) {
471 /* EOF */
472 break;
474 if (ret != sizeof(namelen)) {
475 DEBUG(10,("cups_async_callback: namelen read failed %d %s\n",
476 errno, strerror(errno)));
477 break;
480 DEBUG(11,("cups_async_callback: read namelen %u\n",
481 (unsigned int)namelen));
483 ret = sys_read(fd, &infolen, sizeof(infolen));
484 if (ret == 0) {
485 /* EOF */
486 break;
488 if (ret != sizeof(infolen)) {
489 DEBUG(10,("cups_async_callback: infolen read failed %s\n",
490 strerror(errno)));
491 break;
494 DEBUG(11,("cups_async_callback: read infolen %u\n",
495 (unsigned int)infolen));
497 if (namelen) {
498 name = TALLOC_ARRAY(frame, char, namelen);
499 if (!name) {
500 break;
502 ret = sys_read(fd, name, namelen);
503 if (ret == 0) {
504 /* EOF */
505 break;
507 if (ret != namelen) {
508 DEBUG(10,("cups_async_callback: name read failed %s\n",
509 strerror(errno)));
510 break;
512 DEBUG(11,("cups_async_callback: read name %s\n",
513 name));
514 } else {
515 name = NULL;
517 if (infolen) {
518 info = TALLOC_ARRAY(frame, char, infolen);
519 if (!info) {
520 break;
522 ret = sys_read(fd, info, infolen);
523 if (ret == 0) {
524 /* EOF */
525 break;
527 if (ret != infolen) {
528 DEBUG(10,("cups_async_callback: info read failed %s\n",
529 strerror(errno)));
530 break;
532 DEBUG(11,("cups_async_callback: read info %s\n",
533 info));
534 } else {
535 info = NULL;
538 /* Add to our local pcap cache. */
539 pcap_cache_add_specific(&tmp_pcap_cache, name, info);
540 TALLOC_FREE(name);
541 TALLOC_FREE(info);
544 TALLOC_FREE(frame);
545 if (tmp_pcap_cache) {
546 /* We got a namelist, replace our local cache. */
547 pcap_cache_destroy_specific(&local_pcap_copy);
548 local_pcap_copy = tmp_pcap_cache;
550 /* And the systemwide pcap cache. */
551 pcap_cache_replace(local_pcap_copy);
552 } else {
553 DEBUG(2,("cups_async_callback: failed to read a new "
554 "printer list\n"));
556 close(fd);
557 TALLOC_FREE(p);
558 TALLOC_FREE(cache_fd_event);
561 bool cups_cache_reload(void)
563 int *p_pipe_fd = TALLOC_P(NULL, int);
565 if (!p_pipe_fd) {
566 return false;
569 *p_pipe_fd = -1;
571 /* Set up an async refresh. */
572 if (!cups_pcap_load_async(p_pipe_fd)) {
573 return false;
575 if (!local_pcap_copy) {
576 /* We have no local cache, wait directly for
577 * async refresh to complete.
579 DEBUG(10,("cups_cache_reload: sync read on fd %d\n",
580 *p_pipe_fd ));
582 cups_async_callback(server_event_context(),
583 NULL,
584 EVENT_FD_READ,
585 (void *)p_pipe_fd);
586 if (!local_pcap_copy) {
587 return false;
589 } else {
590 /* Replace the system cache with our
591 * local copy. */
592 pcap_cache_replace(local_pcap_copy);
594 DEBUG(10,("cups_cache_reload: async read on fd %d\n",
595 *p_pipe_fd ));
597 /* Trigger an event when the pipe can be read. */
598 cache_fd_event = event_add_fd(server_event_context(),
599 NULL, *p_pipe_fd,
600 EVENT_FD_READ,
601 cups_async_callback,
602 (void *)p_pipe_fd);
603 if (!cache_fd_event) {
604 close(*p_pipe_fd);
605 TALLOC_FREE(p_pipe_fd);
606 return false;
609 return true;
613 * 'cups_job_delete()' - Delete a job.
616 static int cups_job_delete(const char *sharename, const char *lprm_command, struct printjob *pjob)
618 TALLOC_CTX *frame = talloc_stackframe();
619 int ret = 1; /* Return value */
620 http_t *http = NULL; /* HTTP connection to server */
621 ipp_t *request = NULL, /* IPP Request */
622 *response = NULL; /* IPP Response */
623 cups_lang_t *language = NULL; /* Default language */
624 char *user = NULL;
625 char uri[HTTP_MAX_URI]; /* printer-uri attribute */
626 size_t size;
628 DEBUG(5,("cups_job_delete(%s, %p (%d))\n", sharename, pjob, pjob->sysjob));
631 * Make sure we don't ask for passwords...
634 cupsSetPasswordCB(cups_passwd_cb);
637 * Try to connect to the server...
640 if ((http = cups_connect(frame)) == NULL) {
641 goto out;
645 * Build an IPP_CANCEL_JOB request, which requires the following
646 * attributes:
648 * attributes-charset
649 * attributes-natural-language
650 * job-uri
651 * requesting-user-name
654 request = ippNew();
656 request->request.op.operation_id = IPP_CANCEL_JOB;
657 request->request.op.request_id = 1;
659 language = cupsLangDefault();
661 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
662 "attributes-charset", NULL, "utf-8");
664 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
665 "attributes-natural-language", NULL, language->language);
667 slprintf(uri, sizeof(uri) - 1, "ipp://localhost/jobs/%d", pjob->sysjob);
669 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri", NULL, uri);
671 if (!push_utf8_talloc(frame, &user, pjob->user, &size)) {
672 goto out;
675 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
676 NULL, user);
679 * Do the request and get back a response...
682 if ((response = cupsDoRequest(http, request, "/jobs")) != NULL) {
683 if (response->request.status.status_code >= IPP_OK_CONFLICT) {
684 DEBUG(0,("Unable to cancel job %d - %s\n", pjob->sysjob,
685 ippErrorString(cupsLastError())));
686 } else {
687 ret = 0;
689 } else {
690 DEBUG(0,("Unable to cancel job %d - %s\n", pjob->sysjob,
691 ippErrorString(cupsLastError())));
694 out:
695 if (response)
696 ippDelete(response);
698 if (language)
699 cupsLangFree(language);
701 if (http)
702 httpClose(http);
704 TALLOC_FREE(frame);
705 return ret;
710 * 'cups_job_pause()' - Pause a job.
713 static int cups_job_pause(int snum, struct printjob *pjob)
715 TALLOC_CTX *frame = talloc_stackframe();
716 int ret = 1; /* Return value */
717 http_t *http = NULL; /* HTTP connection to server */
718 ipp_t *request = NULL, /* IPP Request */
719 *response = NULL; /* IPP Response */
720 cups_lang_t *language = NULL; /* Default language */
721 char *user = NULL;
722 char uri[HTTP_MAX_URI]; /* printer-uri attribute */
723 size_t size;
725 DEBUG(5,("cups_job_pause(%d, %p (%d))\n", snum, pjob, pjob->sysjob));
728 * Make sure we don't ask for passwords...
731 cupsSetPasswordCB(cups_passwd_cb);
734 * Try to connect to the server...
737 if ((http = cups_connect(frame)) == NULL) {
738 goto out;
742 * Build an IPP_HOLD_JOB request, which requires the following
743 * attributes:
745 * attributes-charset
746 * attributes-natural-language
747 * job-uri
748 * requesting-user-name
751 request = ippNew();
753 request->request.op.operation_id = IPP_HOLD_JOB;
754 request->request.op.request_id = 1;
756 language = cupsLangDefault();
758 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
759 "attributes-charset", NULL, "utf-8");
761 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
762 "attributes-natural-language", NULL, language->language);
764 slprintf(uri, sizeof(uri) - 1, "ipp://localhost/jobs/%d", pjob->sysjob);
766 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri", NULL, uri);
768 if (!push_utf8_talloc(frame, &user, pjob->user, &size)) {
769 goto out;
771 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
772 NULL, user);
775 * Do the request and get back a response...
778 if ((response = cupsDoRequest(http, request, "/jobs")) != NULL) {
779 if (response->request.status.status_code >= IPP_OK_CONFLICT) {
780 DEBUG(0,("Unable to hold job %d - %s\n", pjob->sysjob,
781 ippErrorString(cupsLastError())));
782 } else {
783 ret = 0;
785 } else {
786 DEBUG(0,("Unable to hold job %d - %s\n", pjob->sysjob,
787 ippErrorString(cupsLastError())));
790 out:
791 if (response)
792 ippDelete(response);
794 if (language)
795 cupsLangFree(language);
797 if (http)
798 httpClose(http);
800 TALLOC_FREE(frame);
801 return ret;
806 * 'cups_job_resume()' - Resume a paused job.
809 static int cups_job_resume(int snum, struct printjob *pjob)
811 TALLOC_CTX *frame = talloc_stackframe();
812 int ret = 1; /* Return value */
813 http_t *http = NULL; /* HTTP connection to server */
814 ipp_t *request = NULL, /* IPP Request */
815 *response = NULL; /* IPP Response */
816 cups_lang_t *language = NULL; /* Default language */
817 char *user = NULL;
818 char uri[HTTP_MAX_URI]; /* printer-uri attribute */
819 size_t size;
821 DEBUG(5,("cups_job_resume(%d, %p (%d))\n", snum, pjob, pjob->sysjob));
824 * Make sure we don't ask for passwords...
827 cupsSetPasswordCB(cups_passwd_cb);
830 * Try to connect to the server...
833 if ((http = cups_connect(frame)) == NULL) {
834 goto out;
838 * Build an IPP_RELEASE_JOB request, which requires the following
839 * attributes:
841 * attributes-charset
842 * attributes-natural-language
843 * job-uri
844 * requesting-user-name
847 request = ippNew();
849 request->request.op.operation_id = IPP_RELEASE_JOB;
850 request->request.op.request_id = 1;
852 language = cupsLangDefault();
854 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
855 "attributes-charset", NULL, "utf-8");
857 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
858 "attributes-natural-language", NULL, language->language);
860 slprintf(uri, sizeof(uri) - 1, "ipp://localhost/jobs/%d", pjob->sysjob);
862 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri", NULL, uri);
864 if (!push_utf8_talloc(frame, &user, pjob->user, &size)) {
865 goto out;
867 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
868 NULL, user);
871 * Do the request and get back a response...
874 if ((response = cupsDoRequest(http, request, "/jobs")) != NULL) {
875 if (response->request.status.status_code >= IPP_OK_CONFLICT) {
876 DEBUG(0,("Unable to release job %d - %s\n", pjob->sysjob,
877 ippErrorString(cupsLastError())));
878 } else {
879 ret = 0;
881 } else {
882 DEBUG(0,("Unable to release job %d - %s\n", pjob->sysjob,
883 ippErrorString(cupsLastError())));
886 out:
887 if (response)
888 ippDelete(response);
890 if (language)
891 cupsLangFree(language);
893 if (http)
894 httpClose(http);
896 TALLOC_FREE(frame);
897 return ret;
902 * 'cups_job_submit()' - Submit a job for printing.
905 static int cups_job_submit(int snum, struct printjob *pjob)
907 TALLOC_CTX *frame = talloc_stackframe();
908 int ret = 1; /* Return value */
909 http_t *http = NULL; /* HTTP connection to server */
910 ipp_t *request = NULL, /* IPP Request */
911 *response = NULL; /* IPP Response */
912 ipp_attribute_t *attr_job_id = NULL; /* IPP Attribute "job-id" */
913 cups_lang_t *language = NULL; /* Default language */
914 char uri[HTTP_MAX_URI]; /* printer-uri attribute */
915 const char *clientname = NULL; /* hostname of client for job-originating-host attribute */
916 char *new_jobname = NULL;
917 int num_options = 0;
918 cups_option_t *options = NULL;
919 char *printername = NULL;
920 char *user = NULL;
921 char *jobname = NULL;
922 char *cupsoptions = NULL;
923 char *filename = NULL;
924 size_t size;
925 uint32_t jobid = (uint32_t)-1;
926 char addr[INET6_ADDRSTRLEN];
928 DEBUG(5,("cups_job_submit(%d, %p)\n", snum, pjob));
931 * Make sure we don't ask for passwords...
934 cupsSetPasswordCB(cups_passwd_cb);
937 * Try to connect to the server...
940 if ((http = cups_connect(frame)) == NULL) {
941 goto out;
945 * Build an IPP_PRINT_JOB request, which requires the following
946 * attributes:
948 * attributes-charset
949 * attributes-natural-language
950 * printer-uri
951 * requesting-user-name
952 * [document-data]
955 request = ippNew();
957 request->request.op.operation_id = IPP_PRINT_JOB;
958 request->request.op.request_id = 1;
960 language = cupsLangDefault();
962 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
963 "attributes-charset", NULL, "utf-8");
965 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
966 "attributes-natural-language", NULL, language->language);
968 if (!push_utf8_talloc(frame, &printername, lp_printername(snum),
969 &size)) {
970 goto out;
972 slprintf(uri, sizeof(uri) - 1, "ipp://localhost/printers/%s",
973 printername);
975 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
976 "printer-uri", NULL, uri);
978 if (!push_utf8_talloc(frame, &user, pjob->user, &size)) {
979 goto out;
981 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
982 NULL, user);
984 clientname = client_name(get_client_fd());
985 if (strcmp(clientname, "UNKNOWN") == 0) {
986 clientname = client_addr(get_client_fd(),addr,sizeof(addr));
989 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
990 "job-originating-host-name", NULL,
991 clientname);
993 /* Get the jobid from the filename. */
994 jobid = print_parse_jobid(pjob->filename);
995 if (jobid == (uint32_t)-1) {
996 DEBUG(0,("cups_job_submit: failed to parse jobid from name %s\n",
997 pjob->filename ));
998 jobid = 0;
1001 if (!push_utf8_talloc(frame, &jobname, pjob->jobname, &size)) {
1002 goto out;
1004 new_jobname = talloc_asprintf(frame,
1005 "%s%.8u %s", PRINT_SPOOL_PREFIX,
1006 (unsigned int)jobid,
1007 jobname);
1008 if (new_jobname == NULL) {
1009 goto out;
1012 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "job-name", NULL,
1013 new_jobname);
1016 * add any options defined in smb.conf
1019 if (!push_utf8_talloc(frame, &cupsoptions, lp_cups_options(snum), &size)) {
1020 goto out;
1022 num_options = 0;
1023 options = NULL;
1024 num_options = cupsParseOptions(cupsoptions, num_options, &options);
1026 if ( num_options )
1027 cupsEncodeOptions(request, num_options, options);
1030 * Do the request and get back a response...
1033 slprintf(uri, sizeof(uri) - 1, "/printers/%s", printername);
1035 if (!push_utf8_talloc(frame, &filename, pjob->filename, &size)) {
1036 goto out;
1038 if ((response = cupsDoFileRequest(http, request, uri, pjob->filename)) != NULL) {
1039 if (response->request.status.status_code >= IPP_OK_CONFLICT) {
1040 DEBUG(0,("Unable to print file to %s - %s\n",
1041 lp_printername(snum),
1042 ippErrorString(cupsLastError())));
1043 } else {
1044 ret = 0;
1045 attr_job_id = ippFindAttribute(response, "job-id", IPP_TAG_INTEGER);
1046 if(attr_job_id) {
1047 pjob->sysjob = attr_job_id->values[0].integer;
1048 DEBUG(5,("cups_job_submit: job-id %d\n", pjob->sysjob));
1049 } else {
1050 DEBUG(0,("Missing job-id attribute in IPP response"));
1053 } else {
1054 DEBUG(0,("Unable to print file to `%s' - %s\n",
1055 lp_printername(snum),
1056 ippErrorString(cupsLastError())));
1059 if ( ret == 0 )
1060 unlink(pjob->filename);
1061 /* else print_job_end will do it for us */
1063 out:
1064 if (response)
1065 ippDelete(response);
1067 if (language)
1068 cupsLangFree(language);
1070 if (http)
1071 httpClose(http);
1073 TALLOC_FREE(frame);
1075 return ret;
1079 * 'cups_queue_get()' - Get all the jobs in the print queue.
1082 static int cups_queue_get(const char *sharename,
1083 enum printing_types printing_type,
1084 char *lpq_command,
1085 print_queue_struct **q,
1086 print_status_struct *status)
1088 TALLOC_CTX *frame = talloc_stackframe();
1089 char *printername = NULL;
1090 http_t *http = NULL; /* HTTP connection to server */
1091 ipp_t *request = NULL, /* IPP Request */
1092 *response = NULL; /* IPP Response */
1093 ipp_attribute_t *attr = NULL; /* Current attribute */
1094 cups_lang_t *language = NULL; /* Default language */
1095 char uri[HTTP_MAX_URI]; /* printer-uri attribute */
1096 int qcount = 0, /* Number of active queue entries */
1097 qalloc = 0; /* Number of queue entries allocated */
1098 print_queue_struct *queue = NULL, /* Queue entries */
1099 *temp; /* Temporary pointer for queue */
1100 char *user_name = NULL, /* job-originating-user-name attribute */
1101 *job_name = NULL; /* job-name attribute */
1102 int job_id; /* job-id attribute */
1103 int job_k_octets; /* job-k-octets attribute */
1104 time_t job_time; /* time-at-creation attribute */
1105 ipp_jstate_t job_status; /* job-status attribute */
1106 int job_priority; /* job-priority attribute */
1107 size_t size;
1108 static const char *jattrs[] = /* Requested job attributes */
1110 "job-id",
1111 "job-k-octets",
1112 "job-name",
1113 "job-originating-user-name",
1114 "job-priority",
1115 "job-state",
1116 "time-at-creation",
1118 static const char *pattrs[] = /* Requested printer attributes */
1120 "printer-state",
1121 "printer-state-message"
1124 *q = NULL;
1126 /* HACK ALERT!!! The problem with support the 'printer name'
1127 option is that we key the tdb off the sharename. So we will
1128 overload the lpq_command string to pass in the printername
1129 (which is basically what we do for non-cups printers ... using
1130 the lpq_command to get the queue listing). */
1132 if (!push_utf8_talloc(frame, &printername, lpq_command, &size)) {
1133 goto out;
1135 DEBUG(5,("cups_queue_get(%s, %p, %p)\n", lpq_command, q, status));
1138 * Make sure we don't ask for passwords...
1141 cupsSetPasswordCB(cups_passwd_cb);
1144 * Try to connect to the server...
1147 if ((http = cups_connect(frame)) == NULL) {
1148 goto out;
1152 * Generate the printer URI...
1155 slprintf(uri, sizeof(uri) - 1, "ipp://localhost/printers/%s", printername);
1158 * Build an IPP_GET_JOBS request, which requires the following
1159 * attributes:
1161 * attributes-charset
1162 * attributes-natural-language
1163 * requested-attributes
1164 * printer-uri
1167 request = ippNew();
1169 request->request.op.operation_id = IPP_GET_JOBS;
1170 request->request.op.request_id = 1;
1172 language = cupsLangDefault();
1174 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
1175 "attributes-charset", NULL, "utf-8");
1177 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
1178 "attributes-natural-language", NULL, language->language);
1180 ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
1181 "requested-attributes",
1182 (sizeof(jattrs) / sizeof(jattrs[0])),
1183 NULL, jattrs);
1185 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
1186 "printer-uri", NULL, uri);
1189 * Do the request and get back a response...
1192 if ((response = cupsDoRequest(http, request, "/")) == NULL) {
1193 DEBUG(0,("Unable to get jobs for %s - %s\n", uri,
1194 ippErrorString(cupsLastError())));
1195 goto out;
1198 if (response->request.status.status_code >= IPP_OK_CONFLICT) {
1199 DEBUG(0,("Unable to get jobs for %s - %s\n", uri,
1200 ippErrorString(response->request.status.status_code)));
1201 goto out;
1205 * Process the jobs...
1208 qcount = 0;
1209 qalloc = 0;
1210 queue = NULL;
1212 for (attr = response->attrs; attr != NULL; attr = attr->next) {
1214 * Skip leading attributes until we hit a job...
1217 while (attr != NULL && attr->group_tag != IPP_TAG_JOB)
1218 attr = attr->next;
1220 if (attr == NULL)
1221 break;
1224 * Allocate memory as needed...
1226 if (qcount >= qalloc) {
1227 qalloc += 16;
1229 queue = SMB_REALLOC_ARRAY(queue, print_queue_struct, qalloc);
1231 if (queue == NULL) {
1232 DEBUG(0,("cups_queue_get: Not enough memory!"));
1233 qcount = 0;
1234 goto out;
1238 temp = queue + qcount;
1239 memset(temp, 0, sizeof(print_queue_struct));
1242 * Pull the needed attributes from this job...
1245 job_id = 0;
1246 job_priority = 50;
1247 job_status = IPP_JOB_PENDING;
1248 job_time = 0;
1249 job_k_octets = 0;
1250 user_name = NULL;
1251 job_name = NULL;
1253 while (attr != NULL && attr->group_tag == IPP_TAG_JOB) {
1254 if (attr->name == NULL) {
1255 attr = attr->next;
1256 break;
1259 if (strcmp(attr->name, "job-id") == 0 &&
1260 attr->value_tag == IPP_TAG_INTEGER)
1261 job_id = attr->values[0].integer;
1263 if (strcmp(attr->name, "job-k-octets") == 0 &&
1264 attr->value_tag == IPP_TAG_INTEGER)
1265 job_k_octets = attr->values[0].integer;
1267 if (strcmp(attr->name, "job-priority") == 0 &&
1268 attr->value_tag == IPP_TAG_INTEGER)
1269 job_priority = attr->values[0].integer;
1271 if (strcmp(attr->name, "job-state") == 0 &&
1272 attr->value_tag == IPP_TAG_ENUM)
1273 job_status = (ipp_jstate_t)(attr->values[0].integer);
1275 if (strcmp(attr->name, "time-at-creation") == 0 &&
1276 attr->value_tag == IPP_TAG_INTEGER)
1277 job_time = attr->values[0].integer;
1279 if (strcmp(attr->name, "job-name") == 0 &&
1280 attr->value_tag == IPP_TAG_NAME) {
1281 if (!pull_utf8_talloc(frame,
1282 &job_name,
1283 attr->values[0].string.text,
1284 &size)) {
1285 goto out;
1289 if (strcmp(attr->name, "job-originating-user-name") == 0 &&
1290 attr->value_tag == IPP_TAG_NAME) {
1291 if (!pull_utf8_talloc(frame,
1292 &user_name,
1293 attr->values[0].string.text,
1294 &size)) {
1295 goto out;
1299 attr = attr->next;
1303 * See if we have everything needed...
1306 if (user_name == NULL || job_name == NULL || job_id == 0) {
1307 if (attr == NULL)
1308 break;
1309 else
1310 continue;
1313 temp->job = job_id;
1314 temp->size = job_k_octets * 1024;
1315 temp->status = job_status == IPP_JOB_PENDING ? LPQ_QUEUED :
1316 job_status == IPP_JOB_STOPPED ? LPQ_PAUSED :
1317 job_status == IPP_JOB_HELD ? LPQ_PAUSED :
1318 LPQ_PRINTING;
1319 temp->priority = job_priority;
1320 temp->time = job_time;
1321 strlcpy(temp->fs_user, user_name, sizeof(temp->fs_user));
1322 strlcpy(temp->fs_file, job_name, sizeof(temp->fs_file));
1324 qcount ++;
1326 if (attr == NULL)
1327 break;
1330 ippDelete(response);
1331 response = NULL;
1334 * Build an IPP_GET_PRINTER_ATTRIBUTES request, which requires the
1335 * following attributes:
1337 * attributes-charset
1338 * attributes-natural-language
1339 * requested-attributes
1340 * printer-uri
1343 request = ippNew();
1345 request->request.op.operation_id = IPP_GET_PRINTER_ATTRIBUTES;
1346 request->request.op.request_id = 1;
1348 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
1349 "attributes-charset", NULL, "utf-8");
1351 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
1352 "attributes-natural-language", NULL, language->language);
1354 ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
1355 "requested-attributes",
1356 (sizeof(pattrs) / sizeof(pattrs[0])),
1357 NULL, pattrs);
1359 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
1360 "printer-uri", NULL, uri);
1363 * Do the request and get back a response...
1366 if ((response = cupsDoRequest(http, request, "/")) == NULL) {
1367 DEBUG(0,("Unable to get printer status for %s - %s\n", printername,
1368 ippErrorString(cupsLastError())));
1369 goto out;
1372 if (response->request.status.status_code >= IPP_OK_CONFLICT) {
1373 DEBUG(0,("Unable to get printer status for %s - %s\n", printername,
1374 ippErrorString(response->request.status.status_code)));
1375 goto out;
1379 * Get the current printer status and convert it to the SAMBA values.
1382 if ((attr = ippFindAttribute(response, "printer-state", IPP_TAG_ENUM)) != NULL) {
1383 if (attr->values[0].integer == IPP_PRINTER_STOPPED)
1384 status->status = LPSTAT_STOPPED;
1385 else
1386 status->status = LPSTAT_OK;
1389 if ((attr = ippFindAttribute(response, "printer-state-message",
1390 IPP_TAG_TEXT)) != NULL) {
1391 char *msg = NULL;
1392 if (!pull_utf8_talloc(frame, &msg,
1393 attr->values[0].string.text,
1394 &size)) {
1395 SAFE_FREE(queue);
1396 qcount = 0;
1397 goto out;
1399 fstrcpy(status->message, msg);
1402 out:
1405 * Return the job queue...
1408 *q = queue;
1410 if (response)
1411 ippDelete(response);
1413 if (language)
1414 cupsLangFree(language);
1416 if (http)
1417 httpClose(http);
1419 TALLOC_FREE(frame);
1420 return qcount;
1425 * 'cups_queue_pause()' - Pause a print queue.
1428 static int cups_queue_pause(int snum)
1430 TALLOC_CTX *frame = talloc_stackframe();
1431 int ret = 1; /* Return value */
1432 http_t *http = NULL; /* HTTP connection to server */
1433 ipp_t *request = NULL, /* IPP Request */
1434 *response = NULL; /* IPP Response */
1435 cups_lang_t *language = NULL; /* Default language */
1436 char *printername = NULL;
1437 char *username = NULL;
1438 char uri[HTTP_MAX_URI]; /* printer-uri attribute */
1439 size_t size;
1441 DEBUG(5,("cups_queue_pause(%d)\n", snum));
1444 * Make sure we don't ask for passwords...
1447 cupsSetPasswordCB(cups_passwd_cb);
1450 * Try to connect to the server...
1453 if ((http = cups_connect(frame)) == NULL) {
1454 goto out;
1458 * Build an IPP_PAUSE_PRINTER request, which requires the following
1459 * attributes:
1461 * attributes-charset
1462 * attributes-natural-language
1463 * printer-uri
1464 * requesting-user-name
1467 request = ippNew();
1469 request->request.op.operation_id = IPP_PAUSE_PRINTER;
1470 request->request.op.request_id = 1;
1472 language = cupsLangDefault();
1474 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
1475 "attributes-charset", NULL, "utf-8");
1477 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
1478 "attributes-natural-language", NULL, language->language);
1480 if (!push_utf8_talloc(frame, &printername, lp_printername(snum),
1481 &size)) {
1482 goto out;
1484 slprintf(uri, sizeof(uri) - 1, "ipp://localhost/printers/%s",
1485 printername);
1487 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, uri);
1489 if (!push_utf8_talloc(frame, &username, current_user_info.unix_name, &size)) {
1490 goto out;
1492 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
1493 NULL, username);
1496 * Do the request and get back a response...
1499 if ((response = cupsDoRequest(http, request, "/admin/")) != NULL) {
1500 if (response->request.status.status_code >= IPP_OK_CONFLICT) {
1501 DEBUG(0,("Unable to pause printer %s - %s\n",
1502 lp_printername(snum),
1503 ippErrorString(cupsLastError())));
1504 } else {
1505 ret = 0;
1507 } else {
1508 DEBUG(0,("Unable to pause printer %s - %s\n",
1509 lp_printername(snum),
1510 ippErrorString(cupsLastError())));
1513 out:
1514 if (response)
1515 ippDelete(response);
1517 if (language)
1518 cupsLangFree(language);
1520 if (http)
1521 httpClose(http);
1523 TALLOC_FREE(frame);
1524 return ret;
1529 * 'cups_queue_resume()' - Restart a print queue.
1532 static int cups_queue_resume(int snum)
1534 TALLOC_CTX *frame = talloc_stackframe();
1535 int ret = 1; /* Return value */
1536 http_t *http = NULL; /* HTTP connection to server */
1537 ipp_t *request = NULL, /* IPP Request */
1538 *response = NULL; /* IPP Response */
1539 cups_lang_t *language = NULL; /* Default language */
1540 char *printername = NULL;
1541 char *username = NULL;
1542 char uri[HTTP_MAX_URI]; /* printer-uri attribute */
1543 size_t size;
1545 DEBUG(5,("cups_queue_resume(%d)\n", snum));
1548 * Make sure we don't ask for passwords...
1551 cupsSetPasswordCB(cups_passwd_cb);
1554 * Try to connect to the server...
1557 if ((http = cups_connect(frame)) == NULL) {
1558 goto out;
1562 * Build an IPP_RESUME_PRINTER request, which requires the following
1563 * attributes:
1565 * attributes-charset
1566 * attributes-natural-language
1567 * printer-uri
1568 * requesting-user-name
1571 request = ippNew();
1573 request->request.op.operation_id = IPP_RESUME_PRINTER;
1574 request->request.op.request_id = 1;
1576 language = cupsLangDefault();
1578 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
1579 "attributes-charset", NULL, "utf-8");
1581 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
1582 "attributes-natural-language", NULL, language->language);
1584 if (!push_utf8_talloc(frame, &printername, lp_printername(snum),
1585 &size)) {
1586 goto out;
1588 slprintf(uri, sizeof(uri) - 1, "ipp://localhost/printers/%s",
1589 printername);
1591 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, uri);
1593 if (!push_utf8_talloc(frame, &username, current_user_info.unix_name, &size)) {
1594 goto out;
1596 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
1597 NULL, username);
1600 * Do the request and get back a response...
1603 if ((response = cupsDoRequest(http, request, "/admin/")) != NULL) {
1604 if (response->request.status.status_code >= IPP_OK_CONFLICT) {
1605 DEBUG(0,("Unable to resume printer %s - %s\n",
1606 lp_printername(snum),
1607 ippErrorString(cupsLastError())));
1608 } else {
1609 ret = 0;
1611 } else {
1612 DEBUG(0,("Unable to resume printer %s - %s\n",
1613 lp_printername(snum),
1614 ippErrorString(cupsLastError())));
1617 out:
1618 if (response)
1619 ippDelete(response);
1621 if (language)
1622 cupsLangFree(language);
1624 if (http)
1625 httpClose(http);
1627 TALLOC_FREE(frame);
1628 return ret;
1631 /*******************************************************************
1632 * CUPS printing interface definitions...
1633 ******************************************************************/
1635 struct printif cups_printif =
1637 PRINT_CUPS,
1638 cups_queue_get,
1639 cups_queue_pause,
1640 cups_queue_resume,
1641 cups_job_delete,
1642 cups_job_pause,
1643 cups_job_resume,
1644 cups_job_submit,
1647 bool cups_pull_comment_location(TALLOC_CTX *mem_ctx,
1648 const char *printername,
1649 char **comment,
1650 char **location)
1652 TALLOC_CTX *frame = talloc_stackframe();
1653 http_t *http = NULL; /* HTTP connection to server */
1654 ipp_t *request = NULL, /* IPP Request */
1655 *response = NULL; /* IPP Response */
1656 ipp_attribute_t *attr; /* Current attribute */
1657 cups_lang_t *language = NULL; /* Default language */
1658 char uri[HTTP_MAX_URI];
1659 char *server = NULL;
1660 char *sharename = NULL;
1661 char *name = NULL;
1662 static const char *requested[] =/* Requested attributes */
1664 "printer-name",
1665 "printer-info",
1666 "printer-location"
1668 bool ret = False;
1669 size_t size;
1671 DEBUG(5, ("pulling %s location\n", printername));
1674 * Make sure we don't ask for passwords...
1677 cupsSetPasswordCB(cups_passwd_cb);
1680 * Try to connect to the server...
1683 if ((http = cups_connect(frame)) == NULL) {
1684 goto out;
1687 request = ippNew();
1689 request->request.op.operation_id = IPP_GET_PRINTER_ATTRIBUTES;
1690 request->request.op.request_id = 1;
1692 language = cupsLangDefault();
1694 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
1695 "attributes-charset", NULL, "utf-8");
1697 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
1698 "attributes-natural-language", NULL, language->language);
1700 if (lp_cups_server() != NULL && strlen(lp_cups_server()) > 0) {
1701 if (!push_utf8_talloc(frame, &server, lp_cups_server(), &size)) {
1702 goto out;
1704 } else {
1705 server = talloc_strdup(frame,cupsServer());
1707 if (server) {
1708 goto out;
1710 if (!push_utf8_talloc(frame, &sharename, printername, &size)) {
1711 goto out;
1713 slprintf(uri, sizeof(uri) - 1, "ipp://%s/printers/%s",
1714 server, sharename);
1716 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
1717 "printer-uri", NULL, uri);
1719 ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
1720 "requested-attributes",
1721 (sizeof(requested) / sizeof(requested[0])),
1722 NULL, requested);
1725 * Do the request and get back a response...
1728 if ((response = cupsDoRequest(http, request, "/")) == NULL) {
1729 DEBUG(0,("Unable to get printer attributes - %s\n",
1730 ippErrorString(cupsLastError())));
1731 goto out;
1734 for (attr = response->attrs; attr != NULL;) {
1736 * Skip leading attributes until we hit a printer...
1739 while (attr != NULL && attr->group_tag != IPP_TAG_PRINTER)
1740 attr = attr->next;
1742 if (attr == NULL)
1743 break;
1746 * Pull the needed attributes from this printer...
1749 while ( attr && (attr->group_tag == IPP_TAG_PRINTER) ) {
1750 if (strcmp(attr->name, "printer-name") == 0 &&
1751 attr->value_tag == IPP_TAG_NAME) {
1752 if (!pull_utf8_talloc(frame,
1753 &name,
1754 attr->values[0].string.text,
1755 &size)) {
1756 goto out;
1760 /* Grab the comment if we don't have one */
1761 if ( (strcmp(attr->name, "printer-info") == 0)
1762 && (attr->value_tag == IPP_TAG_TEXT))
1764 if (!pull_utf8_talloc(mem_ctx,
1765 comment,
1766 attr->values[0].string.text,
1767 &size)) {
1768 goto out;
1770 DEBUG(5,("cups_pull_comment_location: Using cups comment: %s\n",
1771 *comment));
1774 /* Grab the location if we don't have one */
1775 if ( (strcmp(attr->name, "printer-location") == 0)
1776 && (attr->value_tag == IPP_TAG_TEXT))
1778 if (!pull_utf8_talloc(mem_ctx,
1779 location,
1780 attr->values[0].string.text,
1781 &size)) {
1782 goto out;
1784 DEBUG(5,("cups_pull_comment_location: Using cups location: %s\n",
1785 *location));
1788 attr = attr->next;
1792 * We have everything needed...
1795 if (name != NULL)
1796 break;
1799 ret = True;
1801 out:
1802 if (response)
1803 ippDelete(response);
1805 if (request) {
1806 ippDelete(request);
1809 if (language)
1810 cupsLangFree(language);
1812 if (http)
1813 httpClose(http);
1815 TALLOC_FREE(frame);
1816 return ret;
1819 #else
1820 /* this keeps fussy compilers happy */
1821 void print_cups_dummy(void);
1822 void print_cups_dummy(void) {}
1823 #endif /* HAVE_CUPS */