source: branches/samba-3.5.x/source3/printing/print_cups.c

Last change on this file was 664, checked in by Silvan Scherrer, 14 years ago

Samba Server 3.5: fixed a missing return, changed os2_socketpair to os2_pipe

File size: 43.4 KB
Line 
1/*
2 * Support code for the Common UNIX Printing System ("CUPS")
3 *
4 * Copyright 1999-2003 by Michael R Sweet.
5 * Copyright 2008 Jeremy Allison.
6 *
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.
11 *
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.
16 *
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/>.
19 */
20
21/*
22 * JRA. Converted to utf8 pull/push.
23 */
24
25#include "includes.h"
26#include "printing.h"
27#include "librpc/gen_ndr/ndr_printcap.h"
28
29#ifdef HAVE_CUPS
30#include <cups/cups.h>
31#include <cups/language.h>
32
33#ifdef __OS2__
34#define pipe(A) os2_pipe(A)
35#endif
36
37static SIG_ATOMIC_T gotalarm;
38
39/***************************************************************
40 Signal function to tell us we timed out.
41****************************************************************/
42
43static void gotalarm_sig(void)
44{
45 gotalarm = 1;
46}
47
48extern userdom_struct current_user_info;
49
50/*
51 * 'cups_passwd_cb()' - The CUPS password callback...
52 */
53
54static const char * /* O - Password or NULL */
55cups_passwd_cb(const char *prompt) /* I - Prompt */
56{
57 /*
58 * Always return NULL to indicate that no password is available...
59 */
60
61 return (NULL);
62}
63
64static http_t *cups_connect(TALLOC_CTX *frame)
65{
66 http_t *http = NULL;
67 char *server = NULL, *p = NULL;
68 int port;
69 int timeout = lp_cups_connection_timeout();
70 size_t size;
71
72 if (lp_cups_server() != NULL && strlen(lp_cups_server()) > 0) {
73 if (!push_utf8_talloc(frame, &server, lp_cups_server(), &size)) {
74 return NULL;
75 }
76 } else {
77 server = talloc_strdup(frame,cupsServer());
78 }
79 if (!server) {
80 return NULL;
81 }
82
83 p = strchr(server, ':');
84 if (p) {
85 port = atoi(p+1);
86 *p = '\0';
87 } else {
88 port = ippPort();
89 }
90
91 DEBUG(10, ("connecting to cups server %s:%d\n",
92 server, port));
93
94 gotalarm = 0;
95
96 if (timeout) {
97 CatchSignal(SIGALRM, SIGNAL_CAST gotalarm_sig);
98 alarm(timeout);
99 }
100
101#ifdef HAVE_HTTPCONNECTENCRYPT
102 http = httpConnectEncrypt(server, port, lp_cups_encrypt());
103#else
104 http = httpConnect(server, port);
105#endif
106
107
108 CatchSignal(SIGALRM, SIGNAL_CAST SIG_IGN);
109 alarm(0);
110
111 if (http == NULL) {
112 DEBUG(0,("Unable to connect to CUPS server %s:%d - %s\n",
113 server, port, strerror(errno)));
114 }
115
116 return http;
117}
118
119static bool send_pcap_blob(DATA_BLOB *pcap_blob, int fd)
120{
121 size_t ret;
122
123 ret = sys_write(fd, &pcap_blob->length, sizeof(pcap_blob->length));
124 if (ret != sizeof(pcap_blob->length)) {
125 return false;
126 }
127
128 ret = sys_write(fd, pcap_blob->data, pcap_blob->length);
129 if (ret != pcap_blob->length) {
130 return false;
131 }
132
133 DEBUG(10, ("successfully sent blob of len %ld\n", (int64_t)ret));
134 return true;
135}
136
137static bool recv_pcap_blob(TALLOC_CTX *mem_ctx, int fd, DATA_BLOB *pcap_blob)
138{
139 size_t blob_len;
140 size_t ret;
141
142 ret = sys_read(fd, &blob_len, sizeof(blob_len));
143 if (ret != sizeof(blob_len)) {
144 return false;
145 }
146
147 *pcap_blob = data_blob_talloc_named(mem_ctx, NULL, blob_len,
148 "cups pcap");
149 if (pcap_blob->length != blob_len) {
150 return false;
151 }
152 ret = sys_read(fd, pcap_blob->data, blob_len);
153 if (ret != blob_len) {
154 talloc_free(pcap_blob->data);
155 return false;
156 }
157
158 DEBUG(10, ("successfully recvd blob of len %ld\n", (int64_t)ret));
159 return true;
160}
161
162static bool process_cups_printers_response(TALLOC_CTX *mem_ctx,
163 ipp_t *response,
164 struct pcap_data *pcap_data)
165{
166 ipp_attribute_t *attr;
167 char *name;
168 char *info;
169 struct pcap_printer *printer;
170 bool ret_ok = false;
171
172 for (attr = response->attrs; attr != NULL;) {
173 /*
174 * Skip leading attributes until we hit a printer...
175 */
176
177 while (attr != NULL && attr->group_tag != IPP_TAG_PRINTER)
178 attr = attr->next;
179
180 if (attr == NULL)
181 break;
182
183 /*
184 * Pull the needed attributes from this printer...
185 */
186
187 name = NULL;
188 info = NULL;
189
190 while (attr != NULL && attr->group_tag == IPP_TAG_PRINTER) {
191 size_t size;
192 if (strcmp(attr->name, "printer-name") == 0 &&
193 attr->value_tag == IPP_TAG_NAME) {
194 if (!pull_utf8_talloc(mem_ctx,
195 &name,
196 attr->values[0].string.text,
197 &size)) {
198 goto err_out;
199 }
200 }
201
202 if (strcmp(attr->name, "printer-info") == 0 &&
203 attr->value_tag == IPP_TAG_TEXT) {
204 if (!pull_utf8_talloc(mem_ctx,
205 &info,
206 attr->values[0].string.text,
207 &size)) {
208 goto err_out;
209 }
210 }
211
212 attr = attr->next;
213 }
214
215 /*
216 * See if we have everything needed...
217 */
218
219 if (name == NULL)
220 break;
221
222 if (pcap_data->count == 0) {
223 printer = talloc_array(mem_ctx, struct pcap_printer, 1);
224 } else {
225 printer = talloc_realloc(mem_ctx, pcap_data->printers,
226 struct pcap_printer,
227 pcap_data->count + 1);
228 }
229 if (printer == NULL) {
230 goto err_out;
231 }
232 pcap_data->printers = printer;
233 pcap_data->printers[pcap_data->count].name = name;
234 pcap_data->printers[pcap_data->count].info = info;
235 pcap_data->count++;
236 }
237
238 ret_ok = true;
239err_out:
240 return ret_ok;
241}
242
243/*
244 * request printer list from cups, send result back to up parent via fd.
245 * returns true if the (possibly failed) result was successfuly sent to parent.
246 */
247static bool cups_cache_reload_async(int fd)
248{
249 TALLOC_CTX *frame = talloc_stackframe();
250 struct pcap_data pcap_data;
251 http_t *http = NULL; /* HTTP connection to server */
252 ipp_t *request = NULL, /* IPP Request */
253 *response = NULL; /* IPP Response */
254 cups_lang_t *language = NULL; /* Default language */
255 static const char *requested[] =/* Requested attributes */
256 {
257 "printer-name",
258 "printer-info"
259 };
260 bool ret = False;
261 enum ndr_err_code ndr_ret;
262 DATA_BLOB pcap_blob;
263
264 ZERO_STRUCT(pcap_data);
265 pcap_data.status = NT_STATUS_UNSUCCESSFUL;
266
267 DEBUG(5, ("reloading cups printcap cache\n"));
268
269 /*
270 * Make sure we don't ask for passwords...
271 */
272
273 cupsSetPasswordCB(cups_passwd_cb);
274
275 if ((http = cups_connect(frame)) == NULL) {
276 goto out;
277 }
278
279 /*
280 * Build a CUPS_GET_PRINTERS request, which requires the following
281 * attributes:
282 *
283 * attributes-charset
284 * attributes-natural-language
285 * requested-attributes
286 */
287
288 request = ippNew();
289
290 request->request.op.operation_id = CUPS_GET_PRINTERS;
291 request->request.op.request_id = 1;
292
293 language = cupsLangDefault();
294
295 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
296 "attributes-charset", NULL, "utf-8");
297
298 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
299 "attributes-natural-language", NULL, language->language);
300
301 ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
302 "requested-attributes",
303 (sizeof(requested) / sizeof(requested[0])),
304 NULL, requested);
305
306 if ((response = cupsDoRequest(http, request, "/")) == NULL) {
307 DEBUG(0,("Unable to get printer list - %s\n",
308 ippErrorString(cupsLastError())));
309 goto out;
310 }
311
312 ret = process_cups_printers_response(frame, response, &pcap_data);
313 if (!ret) {
314 DEBUG(0,("failed to process cups response\n"));
315 goto out;
316 }
317
318 ippDelete(response);
319 response = NULL;
320
321 /*
322 * Build a CUPS_GET_CLASSES request, which requires the following
323 * attributes:
324 *
325 * attributes-charset
326 * attributes-natural-language
327 * requested-attributes
328 */
329
330 request = ippNew();
331
332 request->request.op.operation_id = CUPS_GET_CLASSES;
333 request->request.op.request_id = 1;
334
335 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
336 "attributes-charset", NULL, "utf-8");
337
338 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
339 "attributes-natural-language", NULL, language->language);
340
341 ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
342 "requested-attributes",
343 (sizeof(requested) / sizeof(requested[0])),
344 NULL, requested);
345
346 if ((response = cupsDoRequest(http, request, "/")) == NULL) {
347 DEBUG(0,("Unable to get printer list - %s\n",
348 ippErrorString(cupsLastError())));
349 goto out;
350 }
351
352 ret = process_cups_printers_response(frame, response, &pcap_data);
353 if (!ret) {
354 DEBUG(0,("failed to process cups response\n"));
355 goto out;
356 }
357
358 pcap_data.status = NT_STATUS_OK;
359 out:
360 if (response)
361 ippDelete(response);
362
363 if (language)
364 cupsLangFree(language);
365
366 if (http)
367 httpClose(http);
368
369 ret = false;
370 ndr_ret = ndr_push_struct_blob(&pcap_blob, frame, NULL, &pcap_data,
371 (ndr_push_flags_fn_t)ndr_push_pcap_data);
372 if (ndr_ret == NDR_ERR_SUCCESS) {
373 ret = send_pcap_blob(&pcap_blob, fd);
374 }
375
376 TALLOC_FREE(frame);
377 return ret;
378}
379
380static struct pcap_cache *local_pcap_copy;
381struct fd_event *cache_fd_event;
382
383static bool cups_pcap_load_async(int *pfd)
384{
385 int fds[2];
386 pid_t pid;
387
388 *pfd = -1;
389
390 if (cache_fd_event) {
391 DEBUG(3,("cups_pcap_load_async: already waiting for "
392 "a refresh event\n" ));
393 return false;
394 }
395
396 DEBUG(5,("cups_pcap_load_async: asynchronously loading cups printers\n"));
397
398 if (pipe(fds) == -1) {
399 return false;
400 }
401
402 pid = sys_fork();
403 if (pid == (pid_t)-1) {
404 DEBUG(10,("cups_pcap_load_async: fork failed %s\n",
405 strerror(errno) ));
406 close(fds[0]);
407 close(fds[1]);
408 return false;
409 }
410
411 if (pid) {
412 DEBUG(10,("cups_pcap_load_async: child pid = %u\n",
413 (unsigned int)pid ));
414 /* Parent. */
415 close(fds[1]);
416 *pfd = fds[0];
417 return true;
418 }
419
420 /* Child. */
421
422 close_all_print_db();
423
424 if (!NT_STATUS_IS_OK(reinit_after_fork(smbd_messaging_context(),
425 smbd_event_context(), true))) {
426 DEBUG(0,("cups_pcap_load_async: reinit_after_fork() failed\n"));
427 smb_panic("cups_pcap_load_async: reinit_after_fork() failed");
428 }
429
430 close(fds[0]);
431 cups_cache_reload_async(fds[1]);
432 close(fds[1]);
433 _exit(0);
434}
435
436struct cups_async_cb_args {
437 int pipe_fd;
438 void (*post_cache_fill_fn)(void);
439};
440
441static void cups_async_callback(struct event_context *event_ctx,
442 struct fd_event *event,
443 uint16 flags,
444 void *p)
445{
446 TALLOC_CTX *frame = talloc_stackframe();
447 struct cups_async_cb_args *cb_args = (struct cups_async_cb_args *)p;
448 struct pcap_cache *tmp_pcap_cache = NULL;
449 bool ret_ok;
450 struct pcap_data pcap_data;
451 DATA_BLOB pcap_blob;
452 enum ndr_err_code ndr_ret;
453 int i;
454
455 DEBUG(5,("cups_async_callback: callback received for printer data. "
456 "fd = %d\n", cb_args->pipe_fd));
457
458 ret_ok = recv_pcap_blob(frame, cb_args->pipe_fd, &pcap_blob);
459 if (!ret_ok) {
460 DEBUG(0,("failed to recv pcap blob\n"));
461 goto err_out;
462 }
463
464 ndr_ret = ndr_pull_struct_blob(&pcap_blob, frame, NULL, &pcap_data,
465 (ndr_pull_flags_fn_t)ndr_pull_pcap_data);
466 if (ndr_ret != NDR_ERR_SUCCESS) {
467 goto err_out;
468 }
469
470 if (!NT_STATUS_IS_OK(pcap_data.status)) {
471 DEBUG(0,("failed to retrieve printer list: %s\n",
472 nt_errstr(pcap_data.status)));
473 goto err_out;
474 }
475
476 for (i = 0; i < pcap_data.count; i++) {
477 ret_ok = pcap_cache_add_specific(&tmp_pcap_cache,
478 pcap_data.printers[i].name,
479 pcap_data.printers[i].info);
480 if (!ret_ok) {
481 DEBUG(0, ("failed to add to tmp pcap cache\n"));
482 break;
483 }
484 }
485
486 if (!ret_ok) {
487 DEBUG(0,("failed to read a new printer list\n"));
488 pcap_cache_destroy_specific(&tmp_pcap_cache);
489 } else {
490 /* We got a possibly empty namelist, replace our local cache. */
491 pcap_cache_destroy_specific(&local_pcap_copy);
492 local_pcap_copy = tmp_pcap_cache;
493
494 /* And the systemwide pcap cache. */
495 pcap_cache_replace(local_pcap_copy);
496
497 /* Caller may have requested post cache fill callback */
498 if (cb_args->post_cache_fill_fn) {
499 cb_args->post_cache_fill_fn();
500 }
501 }
502err_out:
503 TALLOC_FREE(frame);
504 close(cb_args->pipe_fd);
505 TALLOC_FREE(cb_args);
506 TALLOC_FREE(cache_fd_event);
507}
508
509bool cups_cache_reload(void (*post_cache_fill_fn)(void))
510{
511 struct cups_async_cb_args *cb_args;
512 int *p_pipe_fd;
513
514 cb_args = TALLOC_P(NULL, struct cups_async_cb_args);
515 if (!cb_args) {
516 return false;
517 }
518 cb_args->post_cache_fill_fn = post_cache_fill_fn;
519 p_pipe_fd = &cb_args->pipe_fd;
520 *p_pipe_fd = -1;
521
522 /* Set up an async refresh. */
523 if (!cups_pcap_load_async(p_pipe_fd)) {
524 talloc_free(cb_args);
525 return false;
526 }
527 if (!local_pcap_copy) {
528 /* We have no local cache, wait directly for
529 * async refresh to complete.
530 */
531 DEBUG(10,("cups_cache_reload: sync read on fd %d\n",
532 *p_pipe_fd ));
533
534 cups_async_callback(smbd_event_context(),
535 NULL,
536 EVENT_FD_READ,
537 (void *)cb_args);
538 if (!local_pcap_copy) {
539 return false;
540 }
541 } else {
542 /* Replace the system cache with our
543 * local copy. */
544 pcap_cache_replace(local_pcap_copy);
545
546 DEBUG(10,("cups_cache_reload: async read on fd %d\n",
547 *p_pipe_fd ));
548
549 /* Trigger an event when the pipe can be read. */
550 cache_fd_event = event_add_fd(smbd_event_context(),
551 NULL, *p_pipe_fd,
552 EVENT_FD_READ,
553 cups_async_callback,
554 (void *)cb_args);
555 if (!cache_fd_event) {
556 close(*p_pipe_fd);
557 talloc_free(cb_args);
558 return false;
559 }
560 }
561 return true;
562}
563
564/*
565 * 'cups_job_delete()' - Delete a job.
566 */
567
568static int cups_job_delete(const char *sharename, const char *lprm_command, struct printjob *pjob)
569{
570 TALLOC_CTX *frame = talloc_stackframe();
571 int ret = 1; /* Return value */
572 http_t *http = NULL; /* HTTP connection to server */
573 ipp_t *request = NULL, /* IPP Request */
574 *response = NULL; /* IPP Response */
575 cups_lang_t *language = NULL; /* Default language */
576 char *user = NULL;
577 char uri[HTTP_MAX_URI]; /* printer-uri attribute */
578 size_t size;
579
580 DEBUG(5,("cups_job_delete(%s, %p (%d))\n", sharename, pjob, pjob->sysjob));
581
582 /*
583 * Make sure we don't ask for passwords...
584 */
585
586 cupsSetPasswordCB(cups_passwd_cb);
587
588 /*
589 * Try to connect to the server...
590 */
591
592 if ((http = cups_connect(frame)) == NULL) {
593 goto out;
594 }
595
596 /*
597 * Build an IPP_CANCEL_JOB request, which requires the following
598 * attributes:
599 *
600 * attributes-charset
601 * attributes-natural-language
602 * job-uri
603 * requesting-user-name
604 */
605
606 request = ippNew();
607
608 request->request.op.operation_id = IPP_CANCEL_JOB;
609 request->request.op.request_id = 1;
610
611 language = cupsLangDefault();
612
613 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
614 "attributes-charset", NULL, "utf-8");
615
616 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
617 "attributes-natural-language", NULL, language->language);
618
619 slprintf(uri, sizeof(uri) - 1, "ipp://localhost/jobs/%d", pjob->sysjob);
620
621 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri", NULL, uri);
622
623 if (!push_utf8_talloc(frame, &user, pjob->user, &size)) {
624 goto out;
625 }
626
627 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
628 NULL, user);
629
630 /*
631 * Do the request and get back a response...
632 */
633
634 if ((response = cupsDoRequest(http, request, "/jobs")) != NULL) {
635 if (response->request.status.status_code >= IPP_OK_CONFLICT) {
636 DEBUG(0,("Unable to cancel job %d - %s\n", pjob->sysjob,
637 ippErrorString(cupsLastError())));
638 } else {
639 ret = 0;
640 }
641 } else {
642 DEBUG(0,("Unable to cancel job %d - %s\n", pjob->sysjob,
643 ippErrorString(cupsLastError())));
644 }
645
646 out:
647 if (response)
648 ippDelete(response);
649
650 if (language)
651 cupsLangFree(language);
652
653 if (http)
654 httpClose(http);
655
656 TALLOC_FREE(frame);
657 return ret;
658}
659
660
661/*
662 * 'cups_job_pause()' - Pause a job.
663 */
664
665static int cups_job_pause(int snum, struct printjob *pjob)
666{
667 TALLOC_CTX *frame = talloc_stackframe();
668 int ret = 1; /* Return value */
669 http_t *http = NULL; /* HTTP connection to server */
670 ipp_t *request = NULL, /* IPP Request */
671 *response = NULL; /* IPP Response */
672 cups_lang_t *language = NULL; /* Default language */
673 char *user = NULL;
674 char uri[HTTP_MAX_URI]; /* printer-uri attribute */
675 size_t size;
676
677 DEBUG(5,("cups_job_pause(%d, %p (%d))\n", snum, pjob, pjob->sysjob));
678
679 /*
680 * Make sure we don't ask for passwords...
681 */
682
683 cupsSetPasswordCB(cups_passwd_cb);
684
685 /*
686 * Try to connect to the server...
687 */
688
689 if ((http = cups_connect(frame)) == NULL) {
690 goto out;
691 }
692
693 /*
694 * Build an IPP_HOLD_JOB request, which requires the following
695 * attributes:
696 *
697 * attributes-charset
698 * attributes-natural-language
699 * job-uri
700 * requesting-user-name
701 */
702
703 request = ippNew();
704
705 request->request.op.operation_id = IPP_HOLD_JOB;
706 request->request.op.request_id = 1;
707
708 language = cupsLangDefault();
709
710 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
711 "attributes-charset", NULL, "utf-8");
712
713 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
714 "attributes-natural-language", NULL, language->language);
715
716 slprintf(uri, sizeof(uri) - 1, "ipp://localhost/jobs/%d", pjob->sysjob);
717
718 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri", NULL, uri);
719
720 if (!push_utf8_talloc(frame, &user, pjob->user, &size)) {
721 goto out;
722 }
723 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
724 NULL, user);
725
726 /*
727 * Do the request and get back a response...
728 */
729
730 if ((response = cupsDoRequest(http, request, "/jobs")) != NULL) {
731 if (response->request.status.status_code >= IPP_OK_CONFLICT) {
732 DEBUG(0,("Unable to hold job %d - %s\n", pjob->sysjob,
733 ippErrorString(cupsLastError())));
734 } else {
735 ret = 0;
736 }
737 } else {
738 DEBUG(0,("Unable to hold job %d - %s\n", pjob->sysjob,
739 ippErrorString(cupsLastError())));
740 }
741
742 out:
743 if (response)
744 ippDelete(response);
745
746 if (language)
747 cupsLangFree(language);
748
749 if (http)
750 httpClose(http);
751
752 TALLOC_FREE(frame);
753 return ret;
754}
755
756
757/*
758 * 'cups_job_resume()' - Resume a paused job.
759 */
760
761static int cups_job_resume(int snum, struct printjob *pjob)
762{
763 TALLOC_CTX *frame = talloc_stackframe();
764 int ret = 1; /* Return value */
765 http_t *http = NULL; /* HTTP connection to server */
766 ipp_t *request = NULL, /* IPP Request */
767 *response = NULL; /* IPP Response */
768 cups_lang_t *language = NULL; /* Default language */
769 char *user = NULL;
770 char uri[HTTP_MAX_URI]; /* printer-uri attribute */
771 size_t size;
772
773 DEBUG(5,("cups_job_resume(%d, %p (%d))\n", snum, pjob, pjob->sysjob));
774
775 /*
776 * Make sure we don't ask for passwords...
777 */
778
779 cupsSetPasswordCB(cups_passwd_cb);
780
781 /*
782 * Try to connect to the server...
783 */
784
785 if ((http = cups_connect(frame)) == NULL) {
786 goto out;
787 }
788
789 /*
790 * Build an IPP_RELEASE_JOB request, which requires the following
791 * attributes:
792 *
793 * attributes-charset
794 * attributes-natural-language
795 * job-uri
796 * requesting-user-name
797 */
798
799 request = ippNew();
800
801 request->request.op.operation_id = IPP_RELEASE_JOB;
802 request->request.op.request_id = 1;
803
804 language = cupsLangDefault();
805
806 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
807 "attributes-charset", NULL, "utf-8");
808
809 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
810 "attributes-natural-language", NULL, language->language);
811
812 slprintf(uri, sizeof(uri) - 1, "ipp://localhost/jobs/%d", pjob->sysjob);
813
814 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri", NULL, uri);
815
816 if (!push_utf8_talloc(frame, &user, pjob->user, &size)) {
817 goto out;
818 }
819 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
820 NULL, user);
821
822 /*
823 * Do the request and get back a response...
824 */
825
826 if ((response = cupsDoRequest(http, request, "/jobs")) != NULL) {
827 if (response->request.status.status_code >= IPP_OK_CONFLICT) {
828 DEBUG(0,("Unable to release job %d - %s\n", pjob->sysjob,
829 ippErrorString(cupsLastError())));
830 } else {
831 ret = 0;
832 }
833 } else {
834 DEBUG(0,("Unable to release job %d - %s\n", pjob->sysjob,
835 ippErrorString(cupsLastError())));
836 }
837
838 out:
839 if (response)
840 ippDelete(response);
841
842 if (language)
843 cupsLangFree(language);
844
845 if (http)
846 httpClose(http);
847
848 TALLOC_FREE(frame);
849 return ret;
850}
851
852
853/*
854 * 'cups_job_submit()' - Submit a job for printing.
855 */
856
857static int cups_job_submit(int snum, struct printjob *pjob)
858{
859 TALLOC_CTX *frame = talloc_stackframe();
860 int ret = 1; /* Return value */
861 http_t *http = NULL; /* HTTP connection to server */
862 ipp_t *request = NULL, /* IPP Request */
863 *response = NULL; /* IPP Response */
864 ipp_attribute_t *attr_job_id = NULL; /* IPP Attribute "job-id" */
865 cups_lang_t *language = NULL; /* Default language */
866 char uri[HTTP_MAX_URI]; /* printer-uri attribute */
867 const char *clientname = NULL; /* hostname of client for job-originating-host attribute */
868 char *new_jobname = NULL;
869 int num_options = 0;
870 cups_option_t *options = NULL;
871 char *printername = NULL;
872 char *user = NULL;
873 char *jobname = NULL;
874 char *cupsoptions = NULL;
875 char *filename = NULL;
876 size_t size;
877 uint32_t jobid = (uint32_t)-1;
878 char addr[INET6_ADDRSTRLEN];
879
880 DEBUG(5,("cups_job_submit(%d, %p)\n", snum, pjob));
881
882 /*
883 * Make sure we don't ask for passwords...
884 */
885
886 cupsSetPasswordCB(cups_passwd_cb);
887
888 /*
889 * Try to connect to the server...
890 */
891
892 if ((http = cups_connect(frame)) == NULL) {
893 goto out;
894 }
895
896 /*
897 * Build an IPP_PRINT_JOB request, which requires the following
898 * attributes:
899 *
900 * attributes-charset
901 * attributes-natural-language
902 * printer-uri
903 * requesting-user-name
904 * [document-data]
905 */
906
907 request = ippNew();
908
909 request->request.op.operation_id = IPP_PRINT_JOB;
910 request->request.op.request_id = 1;
911
912 language = cupsLangDefault();
913
914 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
915 "attributes-charset", NULL, "utf-8");
916
917 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
918 "attributes-natural-language", NULL, language->language);
919
920 if (!push_utf8_talloc(frame, &printername, PRINTERNAME(snum), &size)) {
921 goto out;
922 }
923 slprintf(uri, sizeof(uri) - 1, "ipp://localhost/printers/%s",
924 printername);
925
926 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
927 "printer-uri", NULL, uri);
928
929 if (!push_utf8_talloc(frame, &user, pjob->user, &size)) {
930 goto out;
931 }
932 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
933 NULL, user);
934
935 clientname = client_name(get_client_fd());
936 if (strcmp(clientname, "UNKNOWN") == 0) {
937 clientname = client_addr(get_client_fd(),addr,sizeof(addr));
938 }
939
940 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
941 "job-originating-host-name", NULL,
942 clientname);
943
944 /* Get the jobid from the filename. */
945 jobid = print_parse_jobid(pjob->filename);
946 if (jobid == (uint32_t)-1) {
947 DEBUG(0,("cups_job_submit: failed to parse jobid from name %s\n",
948 pjob->filename ));
949 jobid = 0;
950 }
951
952 if (!push_utf8_talloc(frame, &jobname, pjob->jobname, &size)) {
953 goto out;
954 }
955 new_jobname = talloc_asprintf(frame,
956 "%s%.8u %s", PRINT_SPOOL_PREFIX,
957 (unsigned int)jobid,
958 jobname);
959 if (new_jobname == NULL) {
960 goto out;
961 }
962
963 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "job-name", NULL,
964 new_jobname);
965
966 /*
967 * add any options defined in smb.conf
968 */
969
970 if (!push_utf8_talloc(frame, &cupsoptions, lp_cups_options(snum), &size)) {
971 goto out;
972 }
973 num_options = 0;
974 options = NULL;
975 num_options = cupsParseOptions(cupsoptions, num_options, &options);
976
977 if ( num_options )
978 cupsEncodeOptions(request, num_options, options);
979
980 /*
981 * Do the request and get back a response...
982 */
983
984 slprintf(uri, sizeof(uri) - 1, "/printers/%s", printername);
985
986 if (!push_utf8_talloc(frame, &filename, pjob->filename, &size)) {
987 goto out;
988 }
989 if ((response = cupsDoFileRequest(http, request, uri, pjob->filename)) != NULL) {
990 if (response->request.status.status_code >= IPP_OK_CONFLICT) {
991 DEBUG(0,("Unable to print file to %s - %s\n", PRINTERNAME(snum),
992 ippErrorString(cupsLastError())));
993 } else {
994 ret = 0;
995 attr_job_id = ippFindAttribute(response, "job-id", IPP_TAG_INTEGER);
996 if(attr_job_id) {
997 pjob->sysjob = attr_job_id->values[0].integer;
998 DEBUG(5,("cups_job_submit: job-id %d\n", pjob->sysjob));
999 } else {
1000 DEBUG(0,("Missing job-id attribute in IPP response"));
1001 }
1002 }
1003 } else {
1004 DEBUG(0,("Unable to print file to `%s' - %s\n", PRINTERNAME(snum),
1005 ippErrorString(cupsLastError())));
1006 }
1007
1008 if ( ret == 0 )
1009 unlink(pjob->filename);
1010 /* else print_job_end will do it for us */
1011
1012 out:
1013 if (response)
1014 ippDelete(response);
1015
1016 if (language)
1017 cupsLangFree(language);
1018
1019 if (http)
1020 httpClose(http);
1021
1022 TALLOC_FREE(frame);
1023
1024 return ret;
1025}
1026
1027/*
1028 * 'cups_queue_get()' - Get all the jobs in the print queue.
1029 */
1030
1031static int cups_queue_get(const char *sharename,
1032 enum printing_types printing_type,
1033 char *lpq_command,
1034 print_queue_struct **q,
1035 print_status_struct *status)
1036{
1037 TALLOC_CTX *frame = talloc_stackframe();
1038 char *printername = NULL;
1039 http_t *http = NULL; /* HTTP connection to server */
1040 ipp_t *request = NULL, /* IPP Request */
1041 *response = NULL; /* IPP Response */
1042 ipp_attribute_t *attr = NULL; /* Current attribute */
1043 cups_lang_t *language = NULL; /* Default language */
1044 char uri[HTTP_MAX_URI]; /* printer-uri attribute */
1045 int qcount = 0, /* Number of active queue entries */
1046 qalloc = 0; /* Number of queue entries allocated */
1047 print_queue_struct *queue = NULL, /* Queue entries */
1048 *temp; /* Temporary pointer for queue */
1049 char *user_name = NULL, /* job-originating-user-name attribute */
1050 *job_name = NULL; /* job-name attribute */
1051 int job_id; /* job-id attribute */
1052 int job_k_octets; /* job-k-octets attribute */
1053 time_t job_time; /* time-at-creation attribute */
1054 ipp_jstate_t job_status; /* job-status attribute */
1055 int job_priority; /* job-priority attribute */
1056 size_t size;
1057 static const char *jattrs[] = /* Requested job attributes */
1058 {
1059 "job-id",
1060 "job-k-octets",
1061 "job-name",
1062 "job-originating-user-name",
1063 "job-priority",
1064 "job-state",
1065 "time-at-creation",
1066 };
1067 static const char *pattrs[] = /* Requested printer attributes */
1068 {
1069 "printer-state",
1070 "printer-state-message"
1071 };
1072
1073 *q = NULL;
1074
1075 /* HACK ALERT!!! The problem with support the 'printer name'
1076 option is that we key the tdb off the sharename. So we will
1077 overload the lpq_command string to pass in the printername
1078 (which is basically what we do for non-cups printers ... using
1079 the lpq_command to get the queue listing). */
1080
1081 if (!push_utf8_talloc(frame, &printername, lpq_command, &size)) {
1082 goto out;
1083 }
1084 DEBUG(5,("cups_queue_get(%s, %p, %p)\n", lpq_command, q, status));
1085
1086 /*
1087 * Make sure we don't ask for passwords...
1088 */
1089
1090 cupsSetPasswordCB(cups_passwd_cb);
1091
1092 /*
1093 * Try to connect to the server...
1094 */
1095
1096 if ((http = cups_connect(frame)) == NULL) {
1097 goto out;
1098 }
1099
1100 /*
1101 * Generate the printer URI...
1102 */
1103
1104 slprintf(uri, sizeof(uri) - 1, "ipp://localhost/printers/%s", printername);
1105
1106 /*
1107 * Build an IPP_GET_JOBS request, which requires the following
1108 * attributes:
1109 *
1110 * attributes-charset
1111 * attributes-natural-language
1112 * requested-attributes
1113 * printer-uri
1114 */
1115
1116 request = ippNew();
1117
1118 request->request.op.operation_id = IPP_GET_JOBS;
1119 request->request.op.request_id = 1;
1120
1121 language = cupsLangDefault();
1122
1123 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
1124 "attributes-charset", NULL, "utf-8");
1125
1126 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
1127 "attributes-natural-language", NULL, language->language);
1128
1129 ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
1130 "requested-attributes",
1131 (sizeof(jattrs) / sizeof(jattrs[0])),
1132 NULL, jattrs);
1133
1134 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
1135 "printer-uri", NULL, uri);
1136
1137 /*
1138 * Do the request and get back a response...
1139 */
1140
1141 if ((response = cupsDoRequest(http, request, "/")) == NULL) {
1142 DEBUG(0,("Unable to get jobs for %s - %s\n", uri,
1143 ippErrorString(cupsLastError())));
1144 goto out;
1145 }
1146
1147 if (response->request.status.status_code >= IPP_OK_CONFLICT) {
1148 DEBUG(0,("Unable to get jobs for %s - %s\n", uri,
1149 ippErrorString(response->request.status.status_code)));
1150 goto out;
1151 }
1152
1153 /*
1154 * Process the jobs...
1155 */
1156
1157 qcount = 0;
1158 qalloc = 0;
1159 queue = NULL;
1160
1161 for (attr = response->attrs; attr != NULL; attr = attr->next) {
1162 /*
1163 * Skip leading attributes until we hit a job...
1164 */
1165
1166 while (attr != NULL && attr->group_tag != IPP_TAG_JOB)
1167 attr = attr->next;
1168
1169 if (attr == NULL)
1170 break;
1171
1172 /*
1173 * Allocate memory as needed...
1174 */
1175 if (qcount >= qalloc) {
1176 qalloc += 16;
1177
1178 queue = SMB_REALLOC_ARRAY(queue, print_queue_struct, qalloc);
1179
1180 if (queue == NULL) {
1181 DEBUG(0,("cups_queue_get: Not enough memory!"));
1182 qcount = 0;
1183 goto out;
1184 }
1185 }
1186
1187 temp = queue + qcount;
1188 memset(temp, 0, sizeof(print_queue_struct));
1189
1190 /*
1191 * Pull the needed attributes from this job...
1192 */
1193
1194 job_id = 0;
1195 job_priority = 50;
1196 job_status = IPP_JOB_PENDING;
1197 job_time = 0;
1198 job_k_octets = 0;
1199 user_name = NULL;
1200 job_name = NULL;
1201
1202 while (attr != NULL && attr->group_tag == IPP_TAG_JOB) {
1203 if (attr->name == NULL) {
1204 attr = attr->next;
1205 break;
1206 }
1207
1208 if (strcmp(attr->name, "job-id") == 0 &&
1209 attr->value_tag == IPP_TAG_INTEGER)
1210 job_id = attr->values[0].integer;
1211
1212 if (strcmp(attr->name, "job-k-octets") == 0 &&
1213 attr->value_tag == IPP_TAG_INTEGER)
1214 job_k_octets = attr->values[0].integer;
1215
1216 if (strcmp(attr->name, "job-priority") == 0 &&
1217 attr->value_tag == IPP_TAG_INTEGER)
1218 job_priority = attr->values[0].integer;
1219
1220 if (strcmp(attr->name, "job-state") == 0 &&
1221 attr->value_tag == IPP_TAG_ENUM)
1222 job_status = (ipp_jstate_t)(attr->values[0].integer);
1223
1224 if (strcmp(attr->name, "time-at-creation") == 0 &&
1225 attr->value_tag == IPP_TAG_INTEGER)
1226 job_time = attr->values[0].integer;
1227
1228 if (strcmp(attr->name, "job-name") == 0 &&
1229 attr->value_tag == IPP_TAG_NAME) {
1230 if (!pull_utf8_talloc(frame,
1231 &job_name,
1232 attr->values[0].string.text,
1233 &size)) {
1234 goto out;
1235 }
1236 }
1237
1238 if (strcmp(attr->name, "job-originating-user-name") == 0 &&
1239 attr->value_tag == IPP_TAG_NAME) {
1240 if (!pull_utf8_talloc(frame,
1241 &user_name,
1242 attr->values[0].string.text,
1243 &size)) {
1244 goto out;
1245 }
1246 }
1247
1248 attr = attr->next;
1249 }
1250
1251 /*
1252 * See if we have everything needed...
1253 */
1254
1255 if (user_name == NULL || job_name == NULL || job_id == 0) {
1256 if (attr == NULL)
1257 break;
1258 else
1259 continue;
1260 }
1261
1262 temp->job = job_id;
1263 temp->size = job_k_octets * 1024;
1264 temp->status = job_status == IPP_JOB_PENDING ? LPQ_QUEUED :
1265 job_status == IPP_JOB_STOPPED ? LPQ_PAUSED :
1266 job_status == IPP_JOB_HELD ? LPQ_PAUSED :
1267 LPQ_PRINTING;
1268 temp->priority = job_priority;
1269 temp->time = job_time;
1270 strlcpy(temp->fs_user, user_name, sizeof(temp->fs_user));
1271 strlcpy(temp->fs_file, job_name, sizeof(temp->fs_file));
1272
1273 qcount ++;
1274
1275 if (attr == NULL)
1276 break;
1277 }
1278
1279 ippDelete(response);
1280 response = NULL;
1281
1282 /*
1283 * Build an IPP_GET_PRINTER_ATTRIBUTES request, which requires the
1284 * following attributes:
1285 *
1286 * attributes-charset
1287 * attributes-natural-language
1288 * requested-attributes
1289 * printer-uri
1290 */
1291
1292 request = ippNew();
1293
1294 request->request.op.operation_id = IPP_GET_PRINTER_ATTRIBUTES;
1295 request->request.op.request_id = 1;
1296
1297 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
1298 "attributes-charset", NULL, "utf-8");
1299
1300 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
1301 "attributes-natural-language", NULL, language->language);
1302
1303 ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
1304 "requested-attributes",
1305 (sizeof(pattrs) / sizeof(pattrs[0])),
1306 NULL, pattrs);
1307
1308 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
1309 "printer-uri", NULL, uri);
1310
1311 /*
1312 * Do the request and get back a response...
1313 */
1314
1315 if ((response = cupsDoRequest(http, request, "/")) == NULL) {
1316 DEBUG(0,("Unable to get printer status for %s - %s\n", printername,
1317 ippErrorString(cupsLastError())));
1318 goto out;
1319 }
1320
1321 if (response->request.status.status_code >= IPP_OK_CONFLICT) {
1322 DEBUG(0,("Unable to get printer status for %s - %s\n", printername,
1323 ippErrorString(response->request.status.status_code)));
1324 goto out;
1325 }
1326
1327 /*
1328 * Get the current printer status and convert it to the SAMBA values.
1329 */
1330
1331 if ((attr = ippFindAttribute(response, "printer-state", IPP_TAG_ENUM)) != NULL) {
1332 if (attr->values[0].integer == IPP_PRINTER_STOPPED)
1333 status->status = LPSTAT_STOPPED;
1334 else
1335 status->status = LPSTAT_OK;
1336 }
1337
1338 if ((attr = ippFindAttribute(response, "printer-state-message",
1339 IPP_TAG_TEXT)) != NULL) {
1340 char *msg = NULL;
1341 if (!pull_utf8_talloc(frame, &msg,
1342 attr->values[0].string.text,
1343 &size)) {
1344 SAFE_FREE(queue);
1345 qcount = 0;
1346 goto out;
1347 }
1348 fstrcpy(status->message, msg);
1349 }
1350
1351 out:
1352
1353 /*
1354 * Return the job queue...
1355 */
1356
1357 *q = queue;
1358
1359 if (response)
1360 ippDelete(response);
1361
1362 if (language)
1363 cupsLangFree(language);
1364
1365 if (http)
1366 httpClose(http);
1367
1368 TALLOC_FREE(frame);
1369 return qcount;
1370}
1371
1372
1373/*
1374 * 'cups_queue_pause()' - Pause a print queue.
1375 */
1376
1377static int cups_queue_pause(int snum)
1378{
1379 TALLOC_CTX *frame = talloc_stackframe();
1380 int ret = 1; /* Return value */
1381 http_t *http = NULL; /* HTTP connection to server */
1382 ipp_t *request = NULL, /* IPP Request */
1383 *response = NULL; /* IPP Response */
1384 cups_lang_t *language = NULL; /* Default language */
1385 char *printername = NULL;
1386 char *username = NULL;
1387 char uri[HTTP_MAX_URI]; /* printer-uri attribute */
1388 size_t size;
1389
1390 DEBUG(5,("cups_queue_pause(%d)\n", snum));
1391
1392 /*
1393 * Make sure we don't ask for passwords...
1394 */
1395
1396 cupsSetPasswordCB(cups_passwd_cb);
1397
1398 /*
1399 * Try to connect to the server...
1400 */
1401
1402 if ((http = cups_connect(frame)) == NULL) {
1403 goto out;
1404 }
1405
1406 /*
1407 * Build an IPP_PAUSE_PRINTER request, which requires the following
1408 * attributes:
1409 *
1410 * attributes-charset
1411 * attributes-natural-language
1412 * printer-uri
1413 * requesting-user-name
1414 */
1415
1416 request = ippNew();
1417
1418 request->request.op.operation_id = IPP_PAUSE_PRINTER;
1419 request->request.op.request_id = 1;
1420
1421 language = cupsLangDefault();
1422
1423 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
1424 "attributes-charset", NULL, "utf-8");
1425
1426 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
1427 "attributes-natural-language", NULL, language->language);
1428
1429 if (!push_utf8_talloc(frame, &printername, PRINTERNAME(snum), &size)) {
1430 goto out;
1431 }
1432 slprintf(uri, sizeof(uri) - 1, "ipp://localhost/printers/%s",
1433 printername);
1434
1435 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, uri);
1436
1437 if (!push_utf8_talloc(frame, &username, current_user_info.unix_name, &size)) {
1438 goto out;
1439 }
1440 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
1441 NULL, username);
1442
1443 /*
1444 * Do the request and get back a response...
1445 */
1446
1447 if ((response = cupsDoRequest(http, request, "/admin/")) != NULL) {
1448 if (response->request.status.status_code >= IPP_OK_CONFLICT) {
1449 DEBUG(0,("Unable to pause printer %s - %s\n", PRINTERNAME(snum),
1450 ippErrorString(cupsLastError())));
1451 } else {
1452 ret = 0;
1453 }
1454 } else {
1455 DEBUG(0,("Unable to pause printer %s - %s\n", PRINTERNAME(snum),
1456 ippErrorString(cupsLastError())));
1457 }
1458
1459 out:
1460 if (response)
1461 ippDelete(response);
1462
1463 if (language)
1464 cupsLangFree(language);
1465
1466 if (http)
1467 httpClose(http);
1468
1469 TALLOC_FREE(frame);
1470 return ret;
1471}
1472
1473
1474/*
1475 * 'cups_queue_resume()' - Restart a print queue.
1476 */
1477
1478static int cups_queue_resume(int snum)
1479{
1480 TALLOC_CTX *frame = talloc_stackframe();
1481 int ret = 1; /* Return value */
1482 http_t *http = NULL; /* HTTP connection to server */
1483 ipp_t *request = NULL, /* IPP Request */
1484 *response = NULL; /* IPP Response */
1485 cups_lang_t *language = NULL; /* Default language */
1486 char *printername = NULL;
1487 char *username = NULL;
1488 char uri[HTTP_MAX_URI]; /* printer-uri attribute */
1489 size_t size;
1490
1491 DEBUG(5,("cups_queue_resume(%d)\n", snum));
1492
1493 /*
1494 * Make sure we don't ask for passwords...
1495 */
1496
1497 cupsSetPasswordCB(cups_passwd_cb);
1498
1499 /*
1500 * Try to connect to the server...
1501 */
1502
1503 if ((http = cups_connect(frame)) == NULL) {
1504 goto out;
1505 }
1506
1507 /*
1508 * Build an IPP_RESUME_PRINTER request, which requires the following
1509 * attributes:
1510 *
1511 * attributes-charset
1512 * attributes-natural-language
1513 * printer-uri
1514 * requesting-user-name
1515 */
1516
1517 request = ippNew();
1518
1519 request->request.op.operation_id = IPP_RESUME_PRINTER;
1520 request->request.op.request_id = 1;
1521
1522 language = cupsLangDefault();
1523
1524 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
1525 "attributes-charset", NULL, "utf-8");
1526
1527 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
1528 "attributes-natural-language", NULL, language->language);
1529
1530 if (!push_utf8_talloc(frame, &printername, PRINTERNAME(snum), &size)) {
1531 goto out;
1532 }
1533 slprintf(uri, sizeof(uri) - 1, "ipp://localhost/printers/%s",
1534 printername);
1535
1536 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, uri);
1537
1538 if (!push_utf8_talloc(frame, &username, current_user_info.unix_name, &size)) {
1539 goto out;
1540 }
1541 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
1542 NULL, username);
1543
1544 /*
1545 * Do the request and get back a response...
1546 */
1547
1548 if ((response = cupsDoRequest(http, request, "/admin/")) != NULL) {
1549 if (response->request.status.status_code >= IPP_OK_CONFLICT) {
1550 DEBUG(0,("Unable to resume printer %s - %s\n", PRINTERNAME(snum),
1551 ippErrorString(cupsLastError())));
1552 } else {
1553 ret = 0;
1554 }
1555 } else {
1556 DEBUG(0,("Unable to resume printer %s - %s\n", PRINTERNAME(snum),
1557 ippErrorString(cupsLastError())));
1558 }
1559
1560 out:
1561 if (response)
1562 ippDelete(response);
1563
1564 if (language)
1565 cupsLangFree(language);
1566
1567 if (http)
1568 httpClose(http);
1569
1570 TALLOC_FREE(frame);
1571 return ret;
1572}
1573
1574/*******************************************************************
1575 * CUPS printing interface definitions...
1576 ******************************************************************/
1577
1578struct printif cups_printif =
1579{
1580 PRINT_CUPS,
1581 cups_queue_get,
1582 cups_queue_pause,
1583 cups_queue_resume,
1584 cups_job_delete,
1585 cups_job_pause,
1586 cups_job_resume,
1587 cups_job_submit,
1588};
1589
1590bool cups_pull_comment_location(NT_PRINTER_INFO_LEVEL_2 *printer)
1591{
1592 TALLOC_CTX *frame = talloc_stackframe();
1593 http_t *http = NULL; /* HTTP connection to server */
1594 ipp_t *request = NULL, /* IPP Request */
1595 *response = NULL; /* IPP Response */
1596 ipp_attribute_t *attr; /* Current attribute */
1597 cups_lang_t *language = NULL; /* Default language */
1598 char uri[HTTP_MAX_URI];
1599 char *sharename = NULL;
1600 char *name = NULL;
1601 static const char *requested[] =/* Requested attributes */
1602 {
1603 "printer-name",
1604 "printer-info",
1605 "printer-location"
1606 };
1607 bool ret = False;
1608 size_t size;
1609
1610 DEBUG(5, ("pulling %s location\n", printer->sharename));
1611
1612 /*
1613 * Make sure we don't ask for passwords...
1614 */
1615
1616 cupsSetPasswordCB(cups_passwd_cb);
1617
1618 /*
1619 * Try to connect to the server...
1620 */
1621
1622 if ((http = cups_connect(frame)) == NULL) {
1623 goto out;
1624 }
1625
1626 request = ippNew();
1627
1628 request->request.op.operation_id = IPP_GET_PRINTER_ATTRIBUTES;
1629 request->request.op.request_id = 1;
1630
1631 language = cupsLangDefault();
1632
1633 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
1634 "attributes-charset", NULL, "utf-8");
1635
1636 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
1637 "attributes-natural-language", NULL, language->language);
1638
1639 if (!push_utf8_talloc(frame, &sharename, printer->sharename, &size)) {
1640 goto out;
1641 }
1642 slprintf(uri, sizeof(uri) - 1, "ipp://localhost/printers/%s",
1643 sharename);
1644
1645 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
1646 "printer-uri", NULL, uri);
1647
1648 ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
1649 "requested-attributes",
1650 (sizeof(requested) / sizeof(requested[0])),
1651 NULL, requested);
1652
1653 /*
1654 * Do the request and get back a response...
1655 */
1656
1657 if ((response = cupsDoRequest(http, request, "/")) == NULL) {
1658 DEBUG(0,("Unable to get printer attributes - %s\n",
1659 ippErrorString(cupsLastError())));
1660 goto out;
1661 }
1662
1663 for (attr = response->attrs; attr != NULL;) {
1664 /*
1665 * Skip leading attributes until we hit a printer...
1666 */
1667
1668 while (attr != NULL && attr->group_tag != IPP_TAG_PRINTER)
1669 attr = attr->next;
1670
1671 if (attr == NULL)
1672 break;
1673
1674 /*
1675 * Pull the needed attributes from this printer...
1676 */
1677
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;
1686 }
1687 }
1688
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)
1692 && !strlen(printer->comment) )
1693 {
1694 char *comment = NULL;
1695 if (!pull_utf8_talloc(frame,
1696 &comment,
1697 attr->values[0].string.text,
1698 &size)) {
1699 goto out;
1700 }
1701 DEBUG(5,("cups_pull_comment_location: Using cups comment: %s\n",
1702 comment));
1703 strlcpy(printer->comment,
1704 comment,
1705 sizeof(printer->comment));
1706 }
1707
1708 /* Grab the location if we don't have one */
1709 if ( (strcmp(attr->name, "printer-location") == 0)
1710 && (attr->value_tag == IPP_TAG_TEXT)
1711 && !strlen(printer->location) )
1712 {
1713 char *location = NULL;
1714 if (!pull_utf8_talloc(frame,
1715 &location,
1716 attr->values[0].string.text,
1717 &size)) {
1718 goto out;
1719 }
1720 DEBUG(5,("cups_pull_comment_location: Using cups location: %s\n",
1721 location));
1722 strlcpy(printer->location,
1723 location,
1724 sizeof(printer->location));
1725 }
1726
1727 attr = attr->next;
1728 }
1729
1730 /*
1731 * We have everything needed...
1732 */
1733
1734 if (name != NULL)
1735 break;
1736 }
1737
1738 ret = True;
1739
1740 out:
1741 if (response)
1742 ippDelete(response);
1743
1744 if (language)
1745 cupsLangFree(language);
1746
1747 if (http)
1748 httpClose(http);
1749
1750 TALLOC_FREE(frame);
1751 return ret;
1752}
1753
1754#else
1755 /* this keeps fussy compilers happy */
1756 void print_cups_dummy(void);
1757 void print_cups_dummy(void) {}
1758#endif /* HAVE_CUPS */
Note: See TracBrowser for help on using the repository browser.