source: branches/samba-3.3.x/source/printing/print_cups.c

Last change on this file was 699, checked in by Silvan Scherrer, 13 years ago

Samba Server 3.3: made it high-mem aware

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