Fix compiler warning in debug message.
[Samba.git] / source3 / printing / print_cups.c
blobda42cb6f85dfa656fc1357a6351a80e4f4c8cae6
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"
28 #include "librpc/gen_ndr/ndr_printcap.h"
30 #ifdef HAVE_CUPS
31 #include <cups/cups.h>
32 #include <cups/language.h>
34 static SIG_ATOMIC_T gotalarm;
36 /***************************************************************
37 Signal function to tell us we timed out.
38 ****************************************************************/
40 static void gotalarm_sig(int signum)
42 gotalarm = 1;
45 extern userdom_struct current_user_info;
48 * 'cups_passwd_cb()' - The CUPS password callback...
51 static const char * /* O - Password or NULL */
52 cups_passwd_cb(const char *prompt) /* I - Prompt */
55 * Always return NULL to indicate that no password is available...
58 return (NULL);
61 static http_t *cups_connect(TALLOC_CTX *frame)
63 http_t *http = NULL;
64 char *server = NULL, *p = NULL;
65 int port;
66 int timeout = lp_cups_connection_timeout();
67 size_t size;
69 if (lp_cups_server() != NULL && strlen(lp_cups_server()) > 0) {
70 if (!push_utf8_talloc(frame, &server, lp_cups_server(), &size)) {
71 return NULL;
73 } else {
74 server = talloc_strdup(frame,cupsServer());
76 if (!server) {
77 return NULL;
80 p = strchr(server, ':');
81 if (p) {
82 port = atoi(p+1);
83 *p = '\0';
84 } else {
85 port = ippPort();
88 DEBUG(10, ("connecting to cups server %s:%d\n",
89 server, port));
91 gotalarm = 0;
93 if (timeout) {
94 CatchSignal(SIGALRM, gotalarm_sig);
95 alarm(timeout);
98 #ifdef HAVE_HTTPCONNECTENCRYPT
99 http = httpConnectEncrypt(server, port, lp_cups_encrypt());
100 #else
101 http = httpConnect(server, port);
102 #endif
105 CatchSignal(SIGALRM, SIG_IGN);
106 alarm(0);
108 if (http == NULL) {
109 DEBUG(0,("Unable to connect to CUPS server %s:%d - %s\n",
110 server, port, strerror(errno)));
113 return http;
116 static bool send_pcap_blob(DATA_BLOB *pcap_blob, int fd)
118 size_t ret;
120 ret = sys_write(fd, &pcap_blob->length, sizeof(pcap_blob->length));
121 if (ret != sizeof(pcap_blob->length)) {
122 return false;
125 ret = sys_write(fd, pcap_blob->data, pcap_blob->length);
126 if (ret != pcap_blob->length) {
127 return false;
130 DEBUG(10, ("successfully sent blob of len %d\n", (int)ret));
131 return true;
134 static bool recv_pcap_blob(TALLOC_CTX *mem_ctx, int fd, DATA_BLOB *pcap_blob)
136 size_t blob_len;
137 size_t ret;
139 ret = sys_read(fd, &blob_len, sizeof(blob_len));
140 if (ret != sizeof(blob_len)) {
141 return false;
144 *pcap_blob = data_blob_talloc_named(mem_ctx, NULL, blob_len,
145 "cups pcap");
146 if (pcap_blob->length != blob_len) {
147 return false;
149 ret = sys_read(fd, pcap_blob->data, blob_len);
150 if (ret != blob_len) {
151 talloc_free(pcap_blob->data);
152 return false;
155 DEBUG(10, ("successfully recvd blob of len %d\n", (int)ret));
156 return true;
159 static bool process_cups_printers_response(TALLOC_CTX *mem_ctx,
160 ipp_t *response,
161 struct pcap_data *pcap_data)
163 ipp_attribute_t *attr;
164 char *name;
165 char *info;
166 struct pcap_printer *printer;
167 bool ret_ok = false;
169 for (attr = response->attrs; attr != NULL;) {
171 * Skip leading attributes until we hit a printer...
174 while (attr != NULL && attr->group_tag != IPP_TAG_PRINTER)
175 attr = attr->next;
177 if (attr == NULL)
178 break;
181 * Pull the needed attributes from this printer...
184 name = NULL;
185 info = NULL;
187 while (attr != NULL && attr->group_tag == IPP_TAG_PRINTER) {
188 size_t size;
189 if (strcmp(attr->name, "printer-name") == 0 &&
190 attr->value_tag == IPP_TAG_NAME) {
191 if (!pull_utf8_talloc(mem_ctx,
192 &name,
193 attr->values[0].string.text,
194 &size)) {
195 goto err_out;
199 if (strcmp(attr->name, "printer-info") == 0 &&
200 attr->value_tag == IPP_TAG_TEXT) {
201 if (!pull_utf8_talloc(mem_ctx,
202 &info,
203 attr->values[0].string.text,
204 &size)) {
205 goto err_out;
209 attr = attr->next;
213 * See if we have everything needed...
216 if (name == NULL)
217 break;
219 if (pcap_data->count == 0) {
220 printer = talloc_array(mem_ctx, struct pcap_printer, 1);
221 } else {
222 printer = talloc_realloc(mem_ctx, pcap_data->printers,
223 struct pcap_printer,
224 pcap_data->count + 1);
226 if (printer == NULL) {
227 goto err_out;
229 pcap_data->printers = printer;
230 pcap_data->printers[pcap_data->count].name = name;
231 pcap_data->printers[pcap_data->count].info = info;
232 pcap_data->count++;
235 ret_ok = true;
236 err_out:
237 return ret_ok;
241 * request printer list from cups, send result back to up parent via fd.
242 * returns true if the (possibly failed) result was successfuly sent to parent.
244 static bool cups_cache_reload_async(int fd)
246 TALLOC_CTX *frame = talloc_stackframe();
247 struct pcap_data pcap_data;
248 http_t *http = NULL; /* HTTP connection to server */
249 ipp_t *request = NULL, /* IPP Request */
250 *response = NULL; /* IPP Response */
251 cups_lang_t *language = NULL; /* Default language */
252 static const char *requested[] =/* Requested attributes */
254 "printer-name",
255 "printer-info"
257 bool ret = False;
258 enum ndr_err_code ndr_ret;
259 DATA_BLOB pcap_blob;
261 ZERO_STRUCT(pcap_data);
262 pcap_data.status = NT_STATUS_UNSUCCESSFUL;
264 DEBUG(5, ("reloading cups printcap cache\n"));
267 * Make sure we don't ask for passwords...
270 cupsSetPasswordCB(cups_passwd_cb);
272 if ((http = cups_connect(frame)) == NULL) {
273 goto out;
277 * Build a CUPS_GET_PRINTERS request, which requires the following
278 * attributes:
280 * attributes-charset
281 * attributes-natural-language
282 * requested-attributes
285 request = ippNew();
287 request->request.op.operation_id = CUPS_GET_PRINTERS;
288 request->request.op.request_id = 1;
290 language = cupsLangDefault();
292 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
293 "attributes-charset", NULL, "utf-8");
295 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
296 "attributes-natural-language", NULL, language->language);
298 ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
299 "requested-attributes",
300 (sizeof(requested) / sizeof(requested[0])),
301 NULL, requested);
303 if ((response = cupsDoRequest(http, request, "/")) == NULL) {
304 DEBUG(0,("Unable to get printer list - %s\n",
305 ippErrorString(cupsLastError())));
306 goto out;
309 ret = process_cups_printers_response(frame, response, &pcap_data);
310 if (!ret) {
311 DEBUG(0,("failed to process cups response\n"));
312 goto out;
315 ippDelete(response);
316 response = NULL;
319 * Build a CUPS_GET_CLASSES request, which requires the following
320 * attributes:
322 * attributes-charset
323 * attributes-natural-language
324 * requested-attributes
327 request = ippNew();
329 request->request.op.operation_id = CUPS_GET_CLASSES;
330 request->request.op.request_id = 1;
332 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
333 "attributes-charset", NULL, "utf-8");
335 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
336 "attributes-natural-language", NULL, language->language);
338 ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
339 "requested-attributes",
340 (sizeof(requested) / sizeof(requested[0])),
341 NULL, requested);
343 if ((response = cupsDoRequest(http, request, "/")) == NULL) {
344 DEBUG(0,("Unable to get printer list - %s\n",
345 ippErrorString(cupsLastError())));
346 goto out;
349 ret = process_cups_printers_response(frame, response, &pcap_data);
350 if (!ret) {
351 DEBUG(0,("failed to process cups response\n"));
352 goto out;
355 pcap_data.status = NT_STATUS_OK;
356 out:
357 if (response)
358 ippDelete(response);
360 if (language)
361 cupsLangFree(language);
363 if (http)
364 httpClose(http);
366 ret = false;
367 ndr_ret = ndr_push_struct_blob(&pcap_blob, frame, &pcap_data,
368 (ndr_push_flags_fn_t)ndr_push_pcap_data);
369 if (ndr_ret == NDR_ERR_SUCCESS) {
370 ret = send_pcap_blob(&pcap_blob, fd);
373 TALLOC_FREE(frame);
374 return ret;
377 static struct fd_event *cache_fd_event;
379 static bool cups_pcap_load_async(struct tevent_context *ev,
380 struct messaging_context *msg_ctx,
381 int *pfd)
383 int fds[2];
384 pid_t pid;
385 NTSTATUS status;
387 *pfd = -1;
389 if (cache_fd_event) {
390 DEBUG(3,("cups_pcap_load_async: already waiting for "
391 "a refresh event\n" ));
392 return false;
395 DEBUG(5,("cups_pcap_load_async: asynchronously loading cups printers\n"));
397 if (pipe(fds) == -1) {
398 return false;
401 pid = sys_fork();
402 if (pid == (pid_t)-1) {
403 DEBUG(10,("cups_pcap_load_async: fork failed %s\n",
404 strerror(errno) ));
405 close(fds[0]);
406 close(fds[1]);
407 return false;
410 if (pid) {
411 DEBUG(10,("cups_pcap_load_async: child pid = %u\n",
412 (unsigned int)pid ));
413 /* Parent. */
414 close(fds[1]);
415 *pfd = fds[0];
416 return true;
419 /* Child. */
421 close_all_print_db();
423 status = reinit_after_fork(msg_ctx, ev, procid_self(), true);
424 if (!NT_STATUS_IS_OK(status)) {
425 DEBUG(0,("cups_pcap_load_async: reinit_after_fork() failed\n"));
426 smb_panic("cups_pcap_load_async: reinit_after_fork() failed");
429 close(fds[0]);
430 cups_cache_reload_async(fds[1]);
431 close(fds[1]);
432 _exit(0);
435 struct cups_async_cb_args {
436 int pipe_fd;
437 struct event_context *event_ctx;
438 struct messaging_context *msg_ctx;
439 void (*post_cache_fill_fn)(struct event_context *,
440 struct messaging_context *);
443 static void cups_async_callback(struct event_context *event_ctx,
444 struct fd_event *event,
445 uint16 flags,
446 void *p)
448 TALLOC_CTX *frame = talloc_stackframe();
449 struct cups_async_cb_args *cb_args = (struct cups_async_cb_args *)p;
450 struct pcap_cache *tmp_pcap_cache = NULL;
451 bool ret_ok;
452 struct pcap_data pcap_data;
453 DATA_BLOB pcap_blob;
454 enum ndr_err_code ndr_ret;
455 int i;
457 DEBUG(5,("cups_async_callback: callback received for printer data. "
458 "fd = %d\n", cb_args->pipe_fd));
460 ret_ok = recv_pcap_blob(frame, cb_args->pipe_fd, &pcap_blob);
461 if (!ret_ok) {
462 DEBUG(0,("failed to recv pcap blob\n"));
463 goto err_out;
466 ndr_ret = ndr_pull_struct_blob(&pcap_blob, frame, &pcap_data,
467 (ndr_pull_flags_fn_t)ndr_pull_pcap_data);
468 if (ndr_ret != NDR_ERR_SUCCESS) {
469 goto err_out;
472 if (!NT_STATUS_IS_OK(pcap_data.status)) {
473 DEBUG(0,("failed to retrieve printer list: %s\n",
474 nt_errstr(pcap_data.status)));
475 goto err_out;
478 for (i = 0; i < pcap_data.count; i++) {
479 ret_ok = pcap_cache_add_specific(&tmp_pcap_cache,
480 pcap_data.printers[i].name,
481 pcap_data.printers[i].info);
482 if (!ret_ok) {
483 DEBUG(0, ("failed to add to tmp pcap cache\n"));
484 goto err_out;
488 /* replace the system-wide pcap cache with a (possibly empty) new one */
489 ret_ok = pcap_cache_replace(tmp_pcap_cache);
490 if (!ret_ok) {
491 DEBUG(0, ("failed to replace pcap cache\n"));
492 } else if (cb_args->post_cache_fill_fn != NULL) {
493 /* Caller requested post cache fill callback */
494 cb_args->post_cache_fill_fn(cb_args->event_ctx,
495 cb_args->msg_ctx);
497 err_out:
498 pcap_cache_destroy_specific(&tmp_pcap_cache);
499 TALLOC_FREE(frame);
500 close(cb_args->pipe_fd);
501 TALLOC_FREE(cb_args);
502 TALLOC_FREE(cache_fd_event);
505 bool cups_cache_reload(struct tevent_context *ev,
506 struct messaging_context *msg_ctx,
507 void (*post_cache_fill_fn)(struct tevent_context *,
508 struct messaging_context *))
510 struct cups_async_cb_args *cb_args;
511 int *p_pipe_fd;
513 cb_args = TALLOC_P(NULL, struct cups_async_cb_args);
514 if (cb_args == NULL) {
515 return false;
518 cb_args->post_cache_fill_fn = post_cache_fill_fn;
519 cb_args->event_ctx = ev;
520 cb_args->msg_ctx = msg_ctx;
521 p_pipe_fd = &cb_args->pipe_fd;
522 *p_pipe_fd = -1;
524 /* Set up an async refresh. */
525 if (!cups_pcap_load_async(ev, msg_ctx, p_pipe_fd)) {
526 talloc_free(cb_args);
527 return false;
530 DEBUG(10,("cups_cache_reload: async read on fd %d\n",
531 *p_pipe_fd ));
533 /* Trigger an event when the pipe can be read. */
534 cache_fd_event = event_add_fd(ev,
535 NULL, *p_pipe_fd,
536 EVENT_FD_READ,
537 cups_async_callback,
538 (void *)cb_args);
539 if (!cache_fd_event) {
540 close(*p_pipe_fd);
541 TALLOC_FREE(cb_args);
542 return false;
545 return true;
549 * 'cups_job_delete()' - Delete a job.
552 static int cups_job_delete(const char *sharename, const char *lprm_command, struct printjob *pjob)
554 TALLOC_CTX *frame = talloc_stackframe();
555 int ret = 1; /* Return value */
556 http_t *http = NULL; /* HTTP connection to server */
557 ipp_t *request = NULL, /* IPP Request */
558 *response = NULL; /* IPP Response */
559 cups_lang_t *language = NULL; /* Default language */
560 char *user = NULL;
561 char uri[HTTP_MAX_URI]; /* printer-uri attribute */
562 size_t size;
564 DEBUG(5,("cups_job_delete(%s, %p (%d))\n", sharename, pjob, pjob->sysjob));
567 * Make sure we don't ask for passwords...
570 cupsSetPasswordCB(cups_passwd_cb);
573 * Try to connect to the server...
576 if ((http = cups_connect(frame)) == NULL) {
577 goto out;
581 * Build an IPP_CANCEL_JOB request, which requires the following
582 * attributes:
584 * attributes-charset
585 * attributes-natural-language
586 * job-uri
587 * requesting-user-name
590 request = ippNew();
592 request->request.op.operation_id = IPP_CANCEL_JOB;
593 request->request.op.request_id = 1;
595 language = cupsLangDefault();
597 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
598 "attributes-charset", NULL, "utf-8");
600 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
601 "attributes-natural-language", NULL, language->language);
603 slprintf(uri, sizeof(uri) - 1, "ipp://localhost/jobs/%d", pjob->sysjob);
605 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri", NULL, uri);
607 if (!push_utf8_talloc(frame, &user, pjob->user, &size)) {
608 goto out;
611 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
612 NULL, user);
615 * Do the request and get back a response...
618 if ((response = cupsDoRequest(http, request, "/jobs")) != NULL) {
619 if (response->request.status.status_code >= IPP_OK_CONFLICT) {
620 DEBUG(0,("Unable to cancel job %d - %s\n", pjob->sysjob,
621 ippErrorString(cupsLastError())));
622 } else {
623 ret = 0;
625 } else {
626 DEBUG(0,("Unable to cancel job %d - %s\n", pjob->sysjob,
627 ippErrorString(cupsLastError())));
630 out:
631 if (response)
632 ippDelete(response);
634 if (language)
635 cupsLangFree(language);
637 if (http)
638 httpClose(http);
640 TALLOC_FREE(frame);
641 return ret;
646 * 'cups_job_pause()' - Pause a job.
649 static int cups_job_pause(int snum, struct printjob *pjob)
651 TALLOC_CTX *frame = talloc_stackframe();
652 int ret = 1; /* Return value */
653 http_t *http = NULL; /* HTTP connection to server */
654 ipp_t *request = NULL, /* IPP Request */
655 *response = NULL; /* IPP Response */
656 cups_lang_t *language = NULL; /* Default language */
657 char *user = NULL;
658 char uri[HTTP_MAX_URI]; /* printer-uri attribute */
659 size_t size;
661 DEBUG(5,("cups_job_pause(%d, %p (%d))\n", snum, pjob, pjob->sysjob));
664 * Make sure we don't ask for passwords...
667 cupsSetPasswordCB(cups_passwd_cb);
670 * Try to connect to the server...
673 if ((http = cups_connect(frame)) == NULL) {
674 goto out;
678 * Build an IPP_HOLD_JOB request, which requires the following
679 * attributes:
681 * attributes-charset
682 * attributes-natural-language
683 * job-uri
684 * requesting-user-name
687 request = ippNew();
689 request->request.op.operation_id = IPP_HOLD_JOB;
690 request->request.op.request_id = 1;
692 language = cupsLangDefault();
694 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
695 "attributes-charset", NULL, "utf-8");
697 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
698 "attributes-natural-language", NULL, language->language);
700 slprintf(uri, sizeof(uri) - 1, "ipp://localhost/jobs/%d", pjob->sysjob);
702 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri", NULL, uri);
704 if (!push_utf8_talloc(frame, &user, pjob->user, &size)) {
705 goto out;
707 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
708 NULL, user);
711 * Do the request and get back a response...
714 if ((response = cupsDoRequest(http, request, "/jobs")) != NULL) {
715 if (response->request.status.status_code >= IPP_OK_CONFLICT) {
716 DEBUG(0,("Unable to hold job %d - %s\n", pjob->sysjob,
717 ippErrorString(cupsLastError())));
718 } else {
719 ret = 0;
721 } else {
722 DEBUG(0,("Unable to hold job %d - %s\n", pjob->sysjob,
723 ippErrorString(cupsLastError())));
726 out:
727 if (response)
728 ippDelete(response);
730 if (language)
731 cupsLangFree(language);
733 if (http)
734 httpClose(http);
736 TALLOC_FREE(frame);
737 return ret;
742 * 'cups_job_resume()' - Resume a paused job.
745 static int cups_job_resume(int snum, struct printjob *pjob)
747 TALLOC_CTX *frame = talloc_stackframe();
748 int ret = 1; /* Return value */
749 http_t *http = NULL; /* HTTP connection to server */
750 ipp_t *request = NULL, /* IPP Request */
751 *response = NULL; /* IPP Response */
752 cups_lang_t *language = NULL; /* Default language */
753 char *user = NULL;
754 char uri[HTTP_MAX_URI]; /* printer-uri attribute */
755 size_t size;
757 DEBUG(5,("cups_job_resume(%d, %p (%d))\n", snum, pjob, pjob->sysjob));
760 * Make sure we don't ask for passwords...
763 cupsSetPasswordCB(cups_passwd_cb);
766 * Try to connect to the server...
769 if ((http = cups_connect(frame)) == NULL) {
770 goto out;
774 * Build an IPP_RELEASE_JOB request, which requires the following
775 * attributes:
777 * attributes-charset
778 * attributes-natural-language
779 * job-uri
780 * requesting-user-name
783 request = ippNew();
785 request->request.op.operation_id = IPP_RELEASE_JOB;
786 request->request.op.request_id = 1;
788 language = cupsLangDefault();
790 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
791 "attributes-charset", NULL, "utf-8");
793 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
794 "attributes-natural-language", NULL, language->language);
796 slprintf(uri, sizeof(uri) - 1, "ipp://localhost/jobs/%d", pjob->sysjob);
798 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri", NULL, uri);
800 if (!push_utf8_talloc(frame, &user, pjob->user, &size)) {
801 goto out;
803 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
804 NULL, user);
807 * Do the request and get back a response...
810 if ((response = cupsDoRequest(http, request, "/jobs")) != NULL) {
811 if (response->request.status.status_code >= IPP_OK_CONFLICT) {
812 DEBUG(0,("Unable to release job %d - %s\n", pjob->sysjob,
813 ippErrorString(cupsLastError())));
814 } else {
815 ret = 0;
817 } else {
818 DEBUG(0,("Unable to release job %d - %s\n", pjob->sysjob,
819 ippErrorString(cupsLastError())));
822 out:
823 if (response)
824 ippDelete(response);
826 if (language)
827 cupsLangFree(language);
829 if (http)
830 httpClose(http);
832 TALLOC_FREE(frame);
833 return ret;
838 * 'cups_job_submit()' - Submit a job for printing.
841 static int cups_job_submit(int snum, struct printjob *pjob)
843 TALLOC_CTX *frame = talloc_stackframe();
844 int ret = 1; /* Return value */
845 http_t *http = NULL; /* HTTP connection to server */
846 ipp_t *request = NULL, /* IPP Request */
847 *response = NULL; /* IPP Response */
848 ipp_attribute_t *attr_job_id = NULL; /* IPP Attribute "job-id" */
849 cups_lang_t *language = NULL; /* Default language */
850 char uri[HTTP_MAX_URI]; /* printer-uri attribute */
851 char *new_jobname = NULL;
852 int num_options = 0;
853 cups_option_t *options = NULL;
854 char *printername = NULL;
855 char *user = NULL;
856 char *jobname = NULL;
857 char *cupsoptions = NULL;
858 char *filename = NULL;
859 size_t size;
860 uint32_t jobid = (uint32_t)-1;
862 DEBUG(5,("cups_job_submit(%d, %p)\n", snum, pjob));
865 * Make sure we don't ask for passwords...
868 cupsSetPasswordCB(cups_passwd_cb);
871 * Try to connect to the server...
874 if ((http = cups_connect(frame)) == NULL) {
875 goto out;
879 * Build an IPP_PRINT_JOB request, which requires the following
880 * attributes:
882 * attributes-charset
883 * attributes-natural-language
884 * printer-uri
885 * requesting-user-name
886 * [document-data]
889 request = ippNew();
891 request->request.op.operation_id = IPP_PRINT_JOB;
892 request->request.op.request_id = 1;
894 language = cupsLangDefault();
896 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
897 "attributes-charset", NULL, "utf-8");
899 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
900 "attributes-natural-language", NULL, language->language);
902 if (!push_utf8_talloc(frame, &printername, lp_printername(snum),
903 &size)) {
904 goto out;
906 slprintf(uri, sizeof(uri) - 1, "ipp://localhost/printers/%s",
907 printername);
909 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
910 "printer-uri", NULL, uri);
912 if (!push_utf8_talloc(frame, &user, pjob->user, &size)) {
913 goto out;
915 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
916 NULL, user);
918 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
919 "job-originating-host-name", NULL,
920 pjob->clientmachine);
922 /* Get the jobid from the filename. */
923 jobid = print_parse_jobid(pjob->filename);
924 if (jobid == (uint32_t)-1) {
925 DEBUG(0,("cups_job_submit: failed to parse jobid from name %s\n",
926 pjob->filename ));
927 jobid = 0;
930 if (!push_utf8_talloc(frame, &jobname, pjob->jobname, &size)) {
931 goto out;
933 new_jobname = talloc_asprintf(frame,
934 "%s%.8u %s", PRINT_SPOOL_PREFIX,
935 (unsigned int)jobid,
936 jobname);
937 if (new_jobname == NULL) {
938 goto out;
941 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "job-name", NULL,
942 new_jobname);
945 * add any options defined in smb.conf
948 if (!push_utf8_talloc(frame, &cupsoptions, lp_cups_options(snum), &size)) {
949 goto out;
951 num_options = 0;
952 options = NULL;
953 num_options = cupsParseOptions(cupsoptions, num_options, &options);
955 if ( num_options )
956 cupsEncodeOptions(request, num_options, options);
959 * Do the request and get back a response...
962 slprintf(uri, sizeof(uri) - 1, "/printers/%s", printername);
964 if (!push_utf8_talloc(frame, &filename, pjob->filename, &size)) {
965 goto out;
967 if ((response = cupsDoFileRequest(http, request, uri, pjob->filename)) != NULL) {
968 if (response->request.status.status_code >= IPP_OK_CONFLICT) {
969 DEBUG(0,("Unable to print file to %s - %s\n",
970 lp_printername(snum),
971 ippErrorString(cupsLastError())));
972 } else {
973 ret = 0;
974 attr_job_id = ippFindAttribute(response, "job-id", IPP_TAG_INTEGER);
975 if(attr_job_id) {
976 pjob->sysjob = attr_job_id->values[0].integer;
977 DEBUG(5,("cups_job_submit: job-id %d\n", pjob->sysjob));
978 } else {
979 DEBUG(0,("Missing job-id attribute in IPP response"));
982 } else {
983 DEBUG(0,("Unable to print file to `%s' - %s\n",
984 lp_printername(snum),
985 ippErrorString(cupsLastError())));
988 if ( ret == 0 )
989 unlink(pjob->filename);
990 /* else print_job_end will do it for us */
992 out:
993 if (response)
994 ippDelete(response);
996 if (language)
997 cupsLangFree(language);
999 if (http)
1000 httpClose(http);
1002 TALLOC_FREE(frame);
1004 return ret;
1008 * 'cups_queue_get()' - Get all the jobs in the print queue.
1011 static int cups_queue_get(const char *sharename,
1012 enum printing_types printing_type,
1013 char *lpq_command,
1014 print_queue_struct **q,
1015 print_status_struct *status)
1017 TALLOC_CTX *frame = talloc_stackframe();
1018 char *printername = NULL;
1019 http_t *http = NULL; /* HTTP connection to server */
1020 ipp_t *request = NULL, /* IPP Request */
1021 *response = NULL; /* IPP Response */
1022 ipp_attribute_t *attr = NULL; /* Current attribute */
1023 cups_lang_t *language = NULL; /* Default language */
1024 char uri[HTTP_MAX_URI]; /* printer-uri attribute */
1025 int qcount = 0, /* Number of active queue entries */
1026 qalloc = 0; /* Number of queue entries allocated */
1027 print_queue_struct *queue = NULL, /* Queue entries */
1028 *temp; /* Temporary pointer for queue */
1029 char *user_name = NULL, /* job-originating-user-name attribute */
1030 *job_name = NULL; /* job-name attribute */
1031 int job_id; /* job-id attribute */
1032 int job_k_octets; /* job-k-octets attribute */
1033 time_t job_time; /* time-at-creation attribute */
1034 ipp_jstate_t job_status; /* job-status attribute */
1035 int job_priority; /* job-priority attribute */
1036 size_t size;
1037 static const char *jattrs[] = /* Requested job attributes */
1039 "job-id",
1040 "job-k-octets",
1041 "job-name",
1042 "job-originating-user-name",
1043 "job-priority",
1044 "job-state",
1045 "time-at-creation",
1047 static const char *pattrs[] = /* Requested printer attributes */
1049 "printer-state",
1050 "printer-state-message"
1053 *q = NULL;
1055 /* HACK ALERT!!! The problem with support the 'printer name'
1056 option is that we key the tdb off the sharename. So we will
1057 overload the lpq_command string to pass in the printername
1058 (which is basically what we do for non-cups printers ... using
1059 the lpq_command to get the queue listing). */
1061 if (!push_utf8_talloc(frame, &printername, lpq_command, &size)) {
1062 goto out;
1064 DEBUG(5,("cups_queue_get(%s, %p, %p)\n", lpq_command, q, status));
1067 * Make sure we don't ask for passwords...
1070 cupsSetPasswordCB(cups_passwd_cb);
1073 * Try to connect to the server...
1076 if ((http = cups_connect(frame)) == NULL) {
1077 goto out;
1081 * Generate the printer URI...
1084 slprintf(uri, sizeof(uri) - 1, "ipp://localhost/printers/%s", printername);
1087 * Build an IPP_GET_JOBS request, which requires the following
1088 * attributes:
1090 * attributes-charset
1091 * attributes-natural-language
1092 * requested-attributes
1093 * printer-uri
1096 request = ippNew();
1098 request->request.op.operation_id = IPP_GET_JOBS;
1099 request->request.op.request_id = 1;
1101 language = cupsLangDefault();
1103 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
1104 "attributes-charset", NULL, "utf-8");
1106 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
1107 "attributes-natural-language", NULL, language->language);
1109 ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
1110 "requested-attributes",
1111 (sizeof(jattrs) / sizeof(jattrs[0])),
1112 NULL, jattrs);
1114 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
1115 "printer-uri", NULL, uri);
1118 * Do the request and get back a response...
1121 if ((response = cupsDoRequest(http, request, "/")) == NULL) {
1122 DEBUG(0,("Unable to get jobs for %s - %s\n", uri,
1123 ippErrorString(cupsLastError())));
1124 goto out;
1127 if (response->request.status.status_code >= IPP_OK_CONFLICT) {
1128 DEBUG(0,("Unable to get jobs for %s - %s\n", uri,
1129 ippErrorString(response->request.status.status_code)));
1130 goto out;
1134 * Process the jobs...
1137 qcount = 0;
1138 qalloc = 0;
1139 queue = NULL;
1141 for (attr = response->attrs; attr != NULL; attr = attr->next) {
1143 * Skip leading attributes until we hit a job...
1146 while (attr != NULL && attr->group_tag != IPP_TAG_JOB)
1147 attr = attr->next;
1149 if (attr == NULL)
1150 break;
1153 * Allocate memory as needed...
1155 if (qcount >= qalloc) {
1156 qalloc += 16;
1158 queue = SMB_REALLOC_ARRAY(queue, print_queue_struct, qalloc);
1160 if (queue == NULL) {
1161 DEBUG(0,("cups_queue_get: Not enough memory!"));
1162 qcount = 0;
1163 goto out;
1167 temp = queue + qcount;
1168 memset(temp, 0, sizeof(print_queue_struct));
1171 * Pull the needed attributes from this job...
1174 job_id = 0;
1175 job_priority = 50;
1176 job_status = IPP_JOB_PENDING;
1177 job_time = 0;
1178 job_k_octets = 0;
1179 user_name = NULL;
1180 job_name = NULL;
1182 while (attr != NULL && attr->group_tag == IPP_TAG_JOB) {
1183 if (attr->name == NULL) {
1184 attr = attr->next;
1185 break;
1188 if (strcmp(attr->name, "job-id") == 0 &&
1189 attr->value_tag == IPP_TAG_INTEGER)
1190 job_id = attr->values[0].integer;
1192 if (strcmp(attr->name, "job-k-octets") == 0 &&
1193 attr->value_tag == IPP_TAG_INTEGER)
1194 job_k_octets = attr->values[0].integer;
1196 if (strcmp(attr->name, "job-priority") == 0 &&
1197 attr->value_tag == IPP_TAG_INTEGER)
1198 job_priority = attr->values[0].integer;
1200 if (strcmp(attr->name, "job-state") == 0 &&
1201 attr->value_tag == IPP_TAG_ENUM)
1202 job_status = (ipp_jstate_t)(attr->values[0].integer);
1204 if (strcmp(attr->name, "time-at-creation") == 0 &&
1205 attr->value_tag == IPP_TAG_INTEGER)
1206 job_time = attr->values[0].integer;
1208 if (strcmp(attr->name, "job-name") == 0 &&
1209 attr->value_tag == IPP_TAG_NAME) {
1210 if (!pull_utf8_talloc(frame,
1211 &job_name,
1212 attr->values[0].string.text,
1213 &size)) {
1214 goto out;
1218 if (strcmp(attr->name, "job-originating-user-name") == 0 &&
1219 attr->value_tag == IPP_TAG_NAME) {
1220 if (!pull_utf8_talloc(frame,
1221 &user_name,
1222 attr->values[0].string.text,
1223 &size)) {
1224 goto out;
1228 attr = attr->next;
1232 * See if we have everything needed...
1235 if (user_name == NULL || job_name == NULL || job_id == 0) {
1236 if (attr == NULL)
1237 break;
1238 else
1239 continue;
1242 temp->job = job_id;
1243 temp->size = job_k_octets * 1024;
1244 temp->status = job_status == IPP_JOB_PENDING ? LPQ_QUEUED :
1245 job_status == IPP_JOB_STOPPED ? LPQ_PAUSED :
1246 job_status == IPP_JOB_HELD ? LPQ_PAUSED :
1247 LPQ_PRINTING;
1248 temp->priority = job_priority;
1249 temp->time = job_time;
1250 strlcpy(temp->fs_user, user_name, sizeof(temp->fs_user));
1251 strlcpy(temp->fs_file, job_name, sizeof(temp->fs_file));
1253 qcount ++;
1255 if (attr == NULL)
1256 break;
1259 ippDelete(response);
1260 response = NULL;
1263 * Build an IPP_GET_PRINTER_ATTRIBUTES request, which requires the
1264 * following attributes:
1266 * attributes-charset
1267 * attributes-natural-language
1268 * requested-attributes
1269 * printer-uri
1272 request = ippNew();
1274 request->request.op.operation_id = IPP_GET_PRINTER_ATTRIBUTES;
1275 request->request.op.request_id = 1;
1277 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
1278 "attributes-charset", NULL, "utf-8");
1280 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
1281 "attributes-natural-language", NULL, language->language);
1283 ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
1284 "requested-attributes",
1285 (sizeof(pattrs) / sizeof(pattrs[0])),
1286 NULL, pattrs);
1288 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
1289 "printer-uri", NULL, uri);
1292 * Do the request and get back a response...
1295 if ((response = cupsDoRequest(http, request, "/")) == NULL) {
1296 DEBUG(0,("Unable to get printer status for %s - %s\n", printername,
1297 ippErrorString(cupsLastError())));
1298 goto out;
1301 if (response->request.status.status_code >= IPP_OK_CONFLICT) {
1302 DEBUG(0,("Unable to get printer status for %s - %s\n", printername,
1303 ippErrorString(response->request.status.status_code)));
1304 goto out;
1308 * Get the current printer status and convert it to the SAMBA values.
1311 if ((attr = ippFindAttribute(response, "printer-state", IPP_TAG_ENUM)) != NULL) {
1312 if (attr->values[0].integer == IPP_PRINTER_STOPPED)
1313 status->status = LPSTAT_STOPPED;
1314 else
1315 status->status = LPSTAT_OK;
1318 if ((attr = ippFindAttribute(response, "printer-state-message",
1319 IPP_TAG_TEXT)) != NULL) {
1320 char *msg = NULL;
1321 if (!pull_utf8_talloc(frame, &msg,
1322 attr->values[0].string.text,
1323 &size)) {
1324 SAFE_FREE(queue);
1325 qcount = 0;
1326 goto out;
1328 fstrcpy(status->message, msg);
1331 out:
1334 * Return the job queue...
1337 *q = queue;
1339 if (response)
1340 ippDelete(response);
1342 if (language)
1343 cupsLangFree(language);
1345 if (http)
1346 httpClose(http);
1348 TALLOC_FREE(frame);
1349 return qcount;
1354 * 'cups_queue_pause()' - Pause a print queue.
1357 static int cups_queue_pause(int snum)
1359 TALLOC_CTX *frame = talloc_stackframe();
1360 int ret = 1; /* Return value */
1361 http_t *http = NULL; /* HTTP connection to server */
1362 ipp_t *request = NULL, /* IPP Request */
1363 *response = NULL; /* IPP Response */
1364 cups_lang_t *language = NULL; /* Default language */
1365 char *printername = NULL;
1366 char *username = NULL;
1367 char uri[HTTP_MAX_URI]; /* printer-uri attribute */
1368 size_t size;
1370 DEBUG(5,("cups_queue_pause(%d)\n", snum));
1373 * Make sure we don't ask for passwords...
1376 cupsSetPasswordCB(cups_passwd_cb);
1379 * Try to connect to the server...
1382 if ((http = cups_connect(frame)) == NULL) {
1383 goto out;
1387 * Build an IPP_PAUSE_PRINTER request, which requires the following
1388 * attributes:
1390 * attributes-charset
1391 * attributes-natural-language
1392 * printer-uri
1393 * requesting-user-name
1396 request = ippNew();
1398 request->request.op.operation_id = IPP_PAUSE_PRINTER;
1399 request->request.op.request_id = 1;
1401 language = cupsLangDefault();
1403 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
1404 "attributes-charset", NULL, "utf-8");
1406 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
1407 "attributes-natural-language", NULL, language->language);
1409 if (!push_utf8_talloc(frame, &printername, lp_printername(snum),
1410 &size)) {
1411 goto out;
1413 slprintf(uri, sizeof(uri) - 1, "ipp://localhost/printers/%s",
1414 printername);
1416 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, uri);
1418 if (!push_utf8_talloc(frame, &username, current_user_info.unix_name, &size)) {
1419 goto out;
1421 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
1422 NULL, username);
1425 * Do the request and get back a response...
1428 if ((response = cupsDoRequest(http, request, "/admin/")) != NULL) {
1429 if (response->request.status.status_code >= IPP_OK_CONFLICT) {
1430 DEBUG(0,("Unable to pause printer %s - %s\n",
1431 lp_printername(snum),
1432 ippErrorString(cupsLastError())));
1433 } else {
1434 ret = 0;
1436 } else {
1437 DEBUG(0,("Unable to pause printer %s - %s\n",
1438 lp_printername(snum),
1439 ippErrorString(cupsLastError())));
1442 out:
1443 if (response)
1444 ippDelete(response);
1446 if (language)
1447 cupsLangFree(language);
1449 if (http)
1450 httpClose(http);
1452 TALLOC_FREE(frame);
1453 return ret;
1458 * 'cups_queue_resume()' - Restart a print queue.
1461 static int cups_queue_resume(int snum)
1463 TALLOC_CTX *frame = talloc_stackframe();
1464 int ret = 1; /* Return value */
1465 http_t *http = NULL; /* HTTP connection to server */
1466 ipp_t *request = NULL, /* IPP Request */
1467 *response = NULL; /* IPP Response */
1468 cups_lang_t *language = NULL; /* Default language */
1469 char *printername = NULL;
1470 char *username = NULL;
1471 char uri[HTTP_MAX_URI]; /* printer-uri attribute */
1472 size_t size;
1474 DEBUG(5,("cups_queue_resume(%d)\n", snum));
1477 * Make sure we don't ask for passwords...
1480 cupsSetPasswordCB(cups_passwd_cb);
1483 * Try to connect to the server...
1486 if ((http = cups_connect(frame)) == NULL) {
1487 goto out;
1491 * Build an IPP_RESUME_PRINTER request, which requires the following
1492 * attributes:
1494 * attributes-charset
1495 * attributes-natural-language
1496 * printer-uri
1497 * requesting-user-name
1500 request = ippNew();
1502 request->request.op.operation_id = IPP_RESUME_PRINTER;
1503 request->request.op.request_id = 1;
1505 language = cupsLangDefault();
1507 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
1508 "attributes-charset", NULL, "utf-8");
1510 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
1511 "attributes-natural-language", NULL, language->language);
1513 if (!push_utf8_talloc(frame, &printername, lp_printername(snum),
1514 &size)) {
1515 goto out;
1517 slprintf(uri, sizeof(uri) - 1, "ipp://localhost/printers/%s",
1518 printername);
1520 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, uri);
1522 if (!push_utf8_talloc(frame, &username, current_user_info.unix_name, &size)) {
1523 goto out;
1525 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
1526 NULL, username);
1529 * Do the request and get back a response...
1532 if ((response = cupsDoRequest(http, request, "/admin/")) != NULL) {
1533 if (response->request.status.status_code >= IPP_OK_CONFLICT) {
1534 DEBUG(0,("Unable to resume printer %s - %s\n",
1535 lp_printername(snum),
1536 ippErrorString(cupsLastError())));
1537 } else {
1538 ret = 0;
1540 } else {
1541 DEBUG(0,("Unable to resume printer %s - %s\n",
1542 lp_printername(snum),
1543 ippErrorString(cupsLastError())));
1546 out:
1547 if (response)
1548 ippDelete(response);
1550 if (language)
1551 cupsLangFree(language);
1553 if (http)
1554 httpClose(http);
1556 TALLOC_FREE(frame);
1557 return ret;
1560 /*******************************************************************
1561 * CUPS printing interface definitions...
1562 ******************************************************************/
1564 struct printif cups_printif =
1566 PRINT_CUPS,
1567 cups_queue_get,
1568 cups_queue_pause,
1569 cups_queue_resume,
1570 cups_job_delete,
1571 cups_job_pause,
1572 cups_job_resume,
1573 cups_job_submit,
1576 bool cups_pull_comment_location(TALLOC_CTX *mem_ctx,
1577 const char *printername,
1578 char **comment,
1579 char **location)
1581 TALLOC_CTX *frame = talloc_stackframe();
1582 http_t *http = NULL; /* HTTP connection to server */
1583 ipp_t *request = NULL, /* IPP Request */
1584 *response = NULL; /* IPP Response */
1585 ipp_attribute_t *attr; /* Current attribute */
1586 cups_lang_t *language = NULL; /* Default language */
1587 char uri[HTTP_MAX_URI];
1588 char *server = NULL;
1589 char *sharename = NULL;
1590 char *name = NULL;
1591 static const char *requested[] =/* Requested attributes */
1593 "printer-name",
1594 "printer-info",
1595 "printer-location"
1597 bool ret = False;
1598 size_t size;
1600 DEBUG(5, ("pulling %s location\n", printername));
1603 * Make sure we don't ask for passwords...
1606 cupsSetPasswordCB(cups_passwd_cb);
1609 * Try to connect to the server...
1612 if ((http = cups_connect(frame)) == NULL) {
1613 goto out;
1616 request = ippNew();
1618 request->request.op.operation_id = IPP_GET_PRINTER_ATTRIBUTES;
1619 request->request.op.request_id = 1;
1621 language = cupsLangDefault();
1623 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
1624 "attributes-charset", NULL, "utf-8");
1626 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
1627 "attributes-natural-language", NULL, language->language);
1629 if (lp_cups_server() != NULL && strlen(lp_cups_server()) > 0) {
1630 if (!push_utf8_talloc(frame, &server, lp_cups_server(), &size)) {
1631 goto out;
1633 } else {
1634 server = talloc_strdup(frame,cupsServer());
1636 if (server) {
1637 goto out;
1639 if (!push_utf8_talloc(frame, &sharename, printername, &size)) {
1640 goto out;
1642 slprintf(uri, sizeof(uri) - 1, "ipp://%s/printers/%s",
1643 server, sharename);
1645 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
1646 "printer-uri", NULL, uri);
1648 ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
1649 "requested-attributes",
1650 (sizeof(requested) / sizeof(requested[0])),
1651 NULL, requested);
1654 * Do the request and get back a response...
1657 if ((response = cupsDoRequest(http, request, "/")) == NULL) {
1658 DEBUG(0,("Unable to get printer attributes - %s\n",
1659 ippErrorString(cupsLastError())));
1660 goto out;
1663 for (attr = response->attrs; attr != NULL;) {
1665 * Skip leading attributes until we hit a printer...
1668 while (attr != NULL && attr->group_tag != IPP_TAG_PRINTER)
1669 attr = attr->next;
1671 if (attr == NULL)
1672 break;
1675 * Pull the needed attributes from this printer...
1678 while ( attr && (attr->group_tag == IPP_TAG_PRINTER) ) {
1679 if (strcmp(attr->name, "printer-name") == 0 &&
1680 attr->value_tag == IPP_TAG_NAME) {
1681 if (!pull_utf8_talloc(frame,
1682 &name,
1683 attr->values[0].string.text,
1684 &size)) {
1685 goto out;
1689 /* Grab the comment if we don't have one */
1690 if ( (strcmp(attr->name, "printer-info") == 0)
1691 && (attr->value_tag == IPP_TAG_TEXT))
1693 if (!pull_utf8_talloc(mem_ctx,
1694 comment,
1695 attr->values[0].string.text,
1696 &size)) {
1697 goto out;
1699 DEBUG(5,("cups_pull_comment_location: Using cups comment: %s\n",
1700 *comment));
1703 /* Grab the location if we don't have one */
1704 if ( (strcmp(attr->name, "printer-location") == 0)
1705 && (attr->value_tag == IPP_TAG_TEXT))
1707 if (!pull_utf8_talloc(mem_ctx,
1708 location,
1709 attr->values[0].string.text,
1710 &size)) {
1711 goto out;
1713 DEBUG(5,("cups_pull_comment_location: Using cups location: %s\n",
1714 *location));
1717 attr = attr->next;
1721 * We have everything needed...
1724 if (name != NULL)
1725 break;
1728 ret = True;
1730 out:
1731 if (response)
1732 ippDelete(response);
1734 if (request) {
1735 ippDelete(request);
1738 if (language)
1739 cupsLangFree(language);
1741 if (http)
1742 httpClose(http);
1744 TALLOC_FREE(frame);
1745 return ret;
1748 #else
1749 /* this keeps fussy compilers happy */
1750 void print_cups_dummy(void);
1751 void print_cups_dummy(void) {}
1752 #endif /* HAVE_CUPS */