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