• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt/router/samba-3.0.25b/source/printing/
1/*
2 * Support code for the Common UNIX Printing System ("CUPS")
3 *
4 * Copyright 1999-2003 by Michael R Sweet.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21#include "includes.h"
22#include "printing.h"
23
24#ifdef HAVE_CUPS
25#include <cups/cups.h>
26#include <cups/language.h>
27
28extern userdom_struct current_user_info;
29
30/*
31 * 'cups_passwd_cb()' - The CUPS password callback...
32 */
33
34static const char *				/* O - Password or NULL */
35cups_passwd_cb(const char *prompt)	/* I - Prompt */
36{
37	/*
38	 * Always return NULL to indicate that no password is available...
39	 */
40
41	return (NULL);
42}
43
44static http_t *cups_connect(void)
45{
46	http_t *http;
47	char *server, *p;
48	int port;
49
50	if (lp_cups_server() != NULL && strlen(lp_cups_server()) > 0) {
51		server = smb_xstrdup(lp_cups_server());
52	} else {
53		server = smb_xstrdup(cupsServer());
54	}
55
56	p = strchr(server, ':');
57	if (p) {
58		port = atoi(p+1);
59		*p = '\0';
60	} else {
61		port = ippPort();
62	}
63
64	DEBUG(10, ("connecting to cups server %s:%d\n",
65		   server, port));
66
67	if ((http = httpConnect(server, port)) == NULL) {
68		DEBUG(0,("Unable to connect to CUPS server %s:%d - %s\n",
69			 server, port, strerror(errno)));
70		SAFE_FREE(server);
71		return NULL;
72	}
73
74	SAFE_FREE(server);
75	return http;
76}
77
78BOOL cups_cache_reload(void)
79{
80	http_t		*http = NULL;		/* HTTP connection to server */
81	ipp_t		*request = NULL,	/* IPP Request */
82			*response = NULL;	/* IPP Response */
83	ipp_attribute_t	*attr;		/* Current attribute */
84	cups_lang_t	*language = NULL;	/* Default language */
85	char		*name,		/* printer-name attribute */
86			*info;		/* printer-info attribute */
87	static const char *requested[] =/* Requested attributes */
88			{
89			  "printer-name",
90			  "printer-info"
91			};
92	BOOL ret = False;
93
94	DEBUG(5, ("reloading cups printcap cache\n"));
95
96       /*
97        * Make sure we don't ask for passwords...
98	*/
99
100        cupsSetPasswordCB(cups_passwd_cb);
101
102       /*
103	* Try to connect to the server...
104	*/
105
106	if ((http = cups_connect()) == NULL) {
107		goto out;
108	}
109
110       /*
111	* Build a CUPS_GET_PRINTERS request, which requires the following
112	* attributes:
113	*
114	*    attributes-charset
115	*    attributes-natural-language
116	*    requested-attributes
117	*/
118
119	request = ippNew();
120
121	request->request.op.operation_id = CUPS_GET_PRINTERS;
122	request->request.op.request_id   = 1;
123
124	language = cupsLangDefault();
125
126	ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
127                     "attributes-charset", NULL, cupsLangEncoding(language));
128
129	ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
130                     "attributes-natural-language", NULL, language->language);
131
132        ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
133	              "requested-attributes",
134		      (sizeof(requested) / sizeof(requested[0])),
135		      NULL, requested);
136
137       /*
138	* Do the request and get back a response...
139	*/
140
141	if ((response = cupsDoRequest(http, request, "/")) == NULL) {
142		DEBUG(0,("Unable to get printer list - %s\n",
143			 ippErrorString(cupsLastError())));
144		goto out;
145	}
146
147	for (attr = response->attrs; attr != NULL;) {
148	       /*
149		* Skip leading attributes until we hit a printer...
150		*/
151
152		while (attr != NULL && attr->group_tag != IPP_TAG_PRINTER)
153			attr = attr->next;
154
155		if (attr == NULL)
156        		break;
157
158	       /*
159		* Pull the needed attributes from this printer...
160		*/
161
162		name       = NULL;
163		info       = NULL;
164
165		while (attr != NULL && attr->group_tag == IPP_TAG_PRINTER) {
166        		if (strcmp(attr->name, "printer-name") == 0 &&
167			    attr->value_tag == IPP_TAG_NAME)
168				name = attr->values[0].string.text;
169
170        		if (strcmp(attr->name, "printer-info") == 0 &&
171			    attr->value_tag == IPP_TAG_TEXT)
172				info = attr->values[0].string.text;
173
174        		attr = attr->next;
175		}
176
177	       /*
178		* See if we have everything needed...
179		*/
180
181		if (name == NULL)
182			break;
183
184		if (!pcap_cache_add(name, info)) {
185			goto out;
186		}
187	}
188
189	ippDelete(response);
190	response = NULL;
191
192       /*
193	* Build a CUPS_GET_CLASSES request, which requires the following
194	* attributes:
195	*
196	*    attributes-charset
197	*    attributes-natural-language
198	*    requested-attributes
199	*/
200
201	request = ippNew();
202
203	request->request.op.operation_id = CUPS_GET_CLASSES;
204	request->request.op.request_id   = 1;
205
206	ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
207                     "attributes-charset", NULL, cupsLangEncoding(language));
208
209	ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
210                     "attributes-natural-language", NULL, language->language);
211
212        ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
213	              "requested-attributes",
214		      (sizeof(requested) / sizeof(requested[0])),
215		      NULL, requested);
216
217       /*
218	* Do the request and get back a response...
219	*/
220
221	if ((response = cupsDoRequest(http, request, "/")) == NULL) {
222		DEBUG(0,("Unable to get printer list - %s\n",
223			 ippErrorString(cupsLastError())));
224		goto out;
225	}
226
227	for (attr = response->attrs; attr != NULL;) {
228	       /*
229		* Skip leading attributes until we hit a printer...
230		*/
231
232		while (attr != NULL && attr->group_tag != IPP_TAG_PRINTER)
233			attr = attr->next;
234
235		if (attr == NULL)
236        		break;
237
238	       /*
239		* Pull the needed attributes from this printer...
240		*/
241
242		name       = NULL;
243		info       = NULL;
244
245		while (attr != NULL && attr->group_tag == IPP_TAG_PRINTER) {
246        		if (strcmp(attr->name, "printer-name") == 0 &&
247			    attr->value_tag == IPP_TAG_NAME)
248				name = attr->values[0].string.text;
249
250        		if (strcmp(attr->name, "printer-info") == 0 &&
251			    attr->value_tag == IPP_TAG_TEXT)
252				info = attr->values[0].string.text;
253
254        		attr = attr->next;
255		}
256
257	       /*
258		* See if we have everything needed...
259		*/
260
261		if (name == NULL)
262			break;
263
264		if (!pcap_cache_add(name, info)) {
265			goto out;
266		}
267	}
268
269	ret = True;
270
271 out:
272	if (response)
273		ippDelete(response);
274
275	if (language)
276		cupsLangFree(language);
277
278	if (http)
279		httpClose(http);
280
281	return ret;
282}
283
284
285/*
286 * 'cups_job_delete()' - Delete a job.
287 */
288
289static int cups_job_delete(const char *sharename, const char *lprm_command, struct printjob *pjob)
290{
291	int		ret = 1;		/* Return value */
292	http_t		*http = NULL;		/* HTTP connection to server */
293	ipp_t		*request = NULL,	/* IPP Request */
294			*response = NULL;	/* IPP Response */
295	cups_lang_t	*language = NULL;	/* Default language */
296	char		uri[HTTP_MAX_URI]; /* printer-uri attribute */
297
298
299	DEBUG(5,("cups_job_delete(%s, %p (%d))\n", sharename, pjob, pjob->sysjob));
300
301       /*
302        * Make sure we don't ask for passwords...
303	*/
304
305        cupsSetPasswordCB(cups_passwd_cb);
306
307       /*
308	* Try to connect to the server...
309	*/
310
311	if ((http = cups_connect()) == NULL) {
312		goto out;
313	}
314
315       /*
316	* Build an IPP_CANCEL_JOB request, which requires the following
317	* attributes:
318	*
319	*    attributes-charset
320	*    attributes-natural-language
321	*    job-uri
322	*    requesting-user-name
323	*/
324
325	request = ippNew();
326
327	request->request.op.operation_id = IPP_CANCEL_JOB;
328	request->request.op.request_id   = 1;
329
330	language = cupsLangDefault();
331
332	ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
333        	     "attributes-charset", NULL, cupsLangEncoding(language));
334
335	ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
336        	     "attributes-natural-language", NULL, language->language);
337
338	slprintf(uri, sizeof(uri) - 1, "ipp://localhost/jobs/%d", pjob->sysjob);
339
340	ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri", NULL, uri);
341
342	ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
343        	     NULL, pjob->user);
344
345       /*
346	* Do the request and get back a response...
347	*/
348
349	if ((response = cupsDoRequest(http, request, "/jobs")) != NULL) {
350		if (response->request.status.status_code >= IPP_OK_CONFLICT) {
351			DEBUG(0,("Unable to cancel job %d - %s\n", pjob->sysjob,
352				ippErrorString(cupsLastError())));
353		} else {
354			ret = 0;
355		}
356	} else {
357		DEBUG(0,("Unable to cancel job %d - %s\n", pjob->sysjob,
358			ippErrorString(cupsLastError())));
359	}
360
361 out:
362	if (response)
363		ippDelete(response);
364
365	if (language)
366		cupsLangFree(language);
367
368	if (http)
369		httpClose(http);
370
371	return ret;
372}
373
374
375/*
376 * 'cups_job_pause()' - Pause a job.
377 */
378
379static int cups_job_pause(int snum, struct printjob *pjob)
380{
381	int		ret = 1;		/* Return value */
382	http_t		*http = NULL;		/* HTTP connection to server */
383	ipp_t		*request = NULL,	/* IPP Request */
384			*response = NULL;	/* IPP Response */
385	cups_lang_t	*language = NULL;	/* Default language */
386	char		uri[HTTP_MAX_URI]; /* printer-uri attribute */
387
388
389	DEBUG(5,("cups_job_pause(%d, %p (%d))\n", snum, pjob, pjob->sysjob));
390
391       /*
392        * Make sure we don't ask for passwords...
393	*/
394
395        cupsSetPasswordCB(cups_passwd_cb);
396
397       /*
398	* Try to connect to the server...
399	*/
400
401	if ((http = cups_connect()) == NULL) {
402		goto out;
403	}
404
405       /*
406	* Build an IPP_HOLD_JOB request, which requires the following
407	* attributes:
408	*
409	*    attributes-charset
410	*    attributes-natural-language
411	*    job-uri
412	*    requesting-user-name
413	*/
414
415	request = ippNew();
416
417	request->request.op.operation_id = IPP_HOLD_JOB;
418	request->request.op.request_id   = 1;
419
420	language = cupsLangDefault();
421
422	ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
423        	     "attributes-charset", NULL, cupsLangEncoding(language));
424
425	ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
426        	     "attributes-natural-language", NULL, language->language);
427
428	slprintf(uri, sizeof(uri) - 1, "ipp://localhost/jobs/%d", pjob->sysjob);
429
430	ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri", NULL, uri);
431
432	ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
433        	     NULL, pjob->user);
434
435       /*
436	* Do the request and get back a response...
437	*/
438
439	if ((response = cupsDoRequest(http, request, "/jobs")) != NULL) {
440		if (response->request.status.status_code >= IPP_OK_CONFLICT) {
441			DEBUG(0,("Unable to hold job %d - %s\n", pjob->sysjob,
442				ippErrorString(cupsLastError())));
443		} else {
444			ret = 0;
445		}
446	} else {
447		DEBUG(0,("Unable to hold job %d - %s\n", pjob->sysjob,
448			ippErrorString(cupsLastError())));
449	}
450
451 out:
452	if (response)
453		ippDelete(response);
454
455	if (language)
456		cupsLangFree(language);
457
458	if (http)
459		httpClose(http);
460
461	return ret;
462}
463
464
465/*
466 * 'cups_job_resume()' - Resume a paused job.
467 */
468
469static int cups_job_resume(int snum, struct printjob *pjob)
470{
471	int		ret = 1;		/* Return value */
472	http_t		*http = NULL;		/* HTTP connection to server */
473	ipp_t		*request = NULL,	/* IPP Request */
474			*response = NULL;	/* IPP Response */
475	cups_lang_t	*language = NULL;	/* Default language */
476	char		uri[HTTP_MAX_URI]; /* printer-uri attribute */
477
478
479	DEBUG(5,("cups_job_resume(%d, %p (%d))\n", snum, pjob, pjob->sysjob));
480
481       /*
482        * Make sure we don't ask for passwords...
483	*/
484
485        cupsSetPasswordCB(cups_passwd_cb);
486
487       /*
488	* Try to connect to the server...
489	*/
490
491	if ((http = cups_connect()) == NULL) {
492		goto out;
493	}
494
495       /*
496	* Build an IPP_RELEASE_JOB request, which requires the following
497	* attributes:
498	*
499	*    attributes-charset
500	*    attributes-natural-language
501	*    job-uri
502	*    requesting-user-name
503	*/
504
505	request = ippNew();
506
507	request->request.op.operation_id = IPP_RELEASE_JOB;
508	request->request.op.request_id   = 1;
509
510	language = cupsLangDefault();
511
512	ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
513        	     "attributes-charset", NULL, cupsLangEncoding(language));
514
515	ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
516        	     "attributes-natural-language", NULL, language->language);
517
518	slprintf(uri, sizeof(uri) - 1, "ipp://localhost/jobs/%d", pjob->sysjob);
519
520	ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri", NULL, uri);
521
522	ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
523        	     NULL, pjob->user);
524
525       /*
526	* Do the request and get back a response...
527	*/
528
529	if ((response = cupsDoRequest(http, request, "/jobs")) != NULL) {
530		if (response->request.status.status_code >= IPP_OK_CONFLICT) {
531			DEBUG(0,("Unable to release job %d - %s\n", pjob->sysjob,
532				ippErrorString(cupsLastError())));
533		} else {
534			ret = 0;
535		}
536	} else {
537		DEBUG(0,("Unable to release job %d - %s\n", pjob->sysjob,
538			ippErrorString(cupsLastError())));
539	}
540
541 out:
542	if (response)
543		ippDelete(response);
544
545	if (language)
546		cupsLangFree(language);
547
548	if (http)
549		httpClose(http);
550
551	return ret;
552}
553
554
555/*
556 * 'cups_job_submit()' - Submit a job for printing.
557 */
558
559static int cups_job_submit(int snum, struct printjob *pjob)
560{
561	int		ret = 1;		/* Return value */
562	http_t		*http = NULL;		/* HTTP connection to server */
563	ipp_t		*request = NULL,	/* IPP Request */
564			*response = NULL;	/* IPP Response */
565	cups_lang_t	*language = NULL;	/* Default language */
566	char		uri[HTTP_MAX_URI]; /* printer-uri attribute */
567	char 		*clientname = NULL; 	/* hostname of client for job-originating-host attribute */
568	pstring		new_jobname;
569	int		num_options = 0;
570	cups_option_t 	*options = NULL;
571
572	DEBUG(5,("cups_job_submit(%d, %p (%d))\n", snum, pjob, pjob->sysjob));
573
574       /*
575        * Make sure we don't ask for passwords...
576	*/
577
578        cupsSetPasswordCB(cups_passwd_cb);
579
580       /*
581	* Try to connect to the server...
582	*/
583
584	if ((http = cups_connect()) == NULL) {
585		goto out;
586	}
587
588       /*
589	* Build an IPP_PRINT_JOB request, which requires the following
590	* attributes:
591	*
592	*    attributes-charset
593	*    attributes-natural-language
594	*    printer-uri
595	*    requesting-user-name
596	*    [document-data]
597	*/
598
599	request = ippNew();
600
601	request->request.op.operation_id = IPP_PRINT_JOB;
602	request->request.op.request_id   = 1;
603
604	language = cupsLangDefault();
605
606	ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
607        	     "attributes-charset", NULL, cupsLangEncoding(language));
608
609	ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
610        	     "attributes-natural-language", NULL, language->language);
611
612	slprintf(uri, sizeof(uri) - 1, "ipp://localhost/printers/%s",
613	         PRINTERNAME(snum));
614
615	ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
616        	     "printer-uri", NULL, uri);
617
618	ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
619        	     NULL, pjob->user);
620
621	clientname = client_name();
622	if (strcmp(clientname, "UNKNOWN") == 0) {
623		clientname = client_addr();
624	}
625
626	ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
627	             "job-originating-host-name", NULL,
628		      clientname);
629
630        pstr_sprintf(new_jobname,"%s%.8u %s", PRINT_SPOOL_PREFIX,
631		(unsigned int)pjob->smbjob, pjob->jobname);
632
633	ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "job-name", NULL,
634        	     new_jobname);
635
636	/*
637	 * add any options defined in smb.conf
638	 */
639
640	num_options = 0;
641	options     = NULL;
642	num_options = cupsParseOptions(lp_cups_options(snum), num_options, &options);
643
644	if ( num_options )
645		cupsEncodeOptions(request, num_options, options);
646
647       /*
648	* Do the request and get back a response...
649	*/
650
651	slprintf(uri, sizeof(uri) - 1, "/printers/%s", PRINTERNAME(snum));
652
653	if ((response = cupsDoFileRequest(http, request, uri, pjob->filename)) != NULL) {
654		if (response->request.status.status_code >= IPP_OK_CONFLICT) {
655			DEBUG(0,("Unable to print file to %s - %s\n", PRINTERNAME(snum),
656			         ippErrorString(cupsLastError())));
657		} else {
658			ret = 0;
659		}
660	} else {
661		DEBUG(0,("Unable to print file to `%s' - %s\n", PRINTERNAME(snum),
662			 ippErrorString(cupsLastError())));
663	}
664
665	if ( ret == 0 )
666		unlink(pjob->filename);
667	/* else print_job_end will do it for us */
668
669 out:
670	if (response)
671		ippDelete(response);
672
673	if (language)
674		cupsLangFree(language);
675
676	if (http)
677		httpClose(http);
678
679	return ret;
680}
681
682/*
683 * 'cups_queue_get()' - Get all the jobs in the print queue.
684 */
685
686static int cups_queue_get(const char *sharename,
687               enum printing_types printing_type,
688               char *lpq_command,
689               print_queue_struct **q,
690               print_status_struct *status)
691{
692	fstring		printername;
693	http_t		*http = NULL;		/* HTTP connection to server */
694	ipp_t		*request = NULL,	/* IPP Request */
695			*response = NULL;	/* IPP Response */
696	ipp_attribute_t	*attr = NULL;		/* Current attribute */
697	cups_lang_t	*language = NULL;	/* Default language */
698	char		uri[HTTP_MAX_URI]; /* printer-uri attribute */
699	int		qcount = 0,		/* Number of active queue entries */
700			qalloc = 0;		/* Number of queue entries allocated */
701	print_queue_struct *queue = NULL,	/* Queue entries */
702			*temp;		/* Temporary pointer for queue */
703	const char	*user_name,	/* job-originating-user-name attribute */
704			*job_name;	/* job-name attribute */
705	int		job_id;		/* job-id attribute */
706	int		job_k_octets;	/* job-k-octets attribute */
707	time_t		job_time;	/* time-at-creation attribute */
708	ipp_jstate_t	job_status;	/* job-status attribute */
709	int		job_priority;	/* job-priority attribute */
710	static const char *jattrs[] =	/* Requested job attributes */
711			{
712			  "job-id",
713			  "job-k-octets",
714			  "job-name",
715			  "job-originating-user-name",
716			  "job-priority",
717			  "job-state",
718			  "time-at-creation",
719			};
720	static const char *pattrs[] =	/* Requested printer attributes */
721			{
722			  "printer-state",
723			  "printer-state-message"
724			};
725
726	*q = NULL;
727
728	/* HACK ALERT!!!  The problem with support the 'printer name'
729	   option is that we key the tdb off the sharename.  So we will
730	   overload the lpq_command string to pass in the printername
731	   (which is basically what we do for non-cups printers ... using
732	   the lpq_command to get the queue listing). */
733
734	fstrcpy( printername, lpq_command );
735
736	DEBUG(5,("cups_queue_get(%s, %p, %p)\n", printername, q, status));
737
738       /*
739        * Make sure we don't ask for passwords...
740	*/
741
742        cupsSetPasswordCB(cups_passwd_cb);
743
744       /*
745	* Try to connect to the server...
746	*/
747
748	if ((http = cups_connect()) == NULL) {
749		goto out;
750	}
751
752       /*
753        * Generate the printer URI...
754	*/
755
756	slprintf(uri, sizeof(uri) - 1, "ipp://localhost/printers/%s", printername);
757
758       /*
759	* Build an IPP_GET_JOBS request, which requires the following
760	* attributes:
761	*
762	*    attributes-charset
763	*    attributes-natural-language
764	*    requested-attributes
765	*    printer-uri
766	*/
767
768	request = ippNew();
769
770	request->request.op.operation_id = IPP_GET_JOBS;
771	request->request.op.request_id   = 1;
772
773	language = cupsLangDefault();
774
775	ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
776                     "attributes-charset", NULL, cupsLangEncoding(language));
777
778	ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
779                     "attributes-natural-language", NULL, language->language);
780
781        ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
782	              "requested-attributes",
783		      (sizeof(jattrs) / sizeof(jattrs[0])),
784		      NULL, jattrs);
785
786	ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
787                     "printer-uri", NULL, uri);
788
789       /*
790	* Do the request and get back a response...
791	*/
792
793	if ((response = cupsDoRequest(http, request, "/")) == NULL) {
794		DEBUG(0,("Unable to get jobs for %s - %s\n", uri,
795			 ippErrorString(cupsLastError())));
796		goto out;
797	}
798
799	if (response->request.status.status_code >= IPP_OK_CONFLICT) {
800		DEBUG(0,("Unable to get jobs for %s - %s\n", uri,
801			 ippErrorString(response->request.status.status_code)));
802		goto out;
803	}
804
805       /*
806        * Process the jobs...
807	*/
808
809        qcount = 0;
810	qalloc = 0;
811	queue  = NULL;
812
813        for (attr = response->attrs; attr != NULL; attr = attr->next) {
814	       /*
815		* Skip leading attributes until we hit a job...
816		*/
817
818		while (attr != NULL && attr->group_tag != IPP_TAG_JOB)
819        		attr = attr->next;
820
821		if (attr == NULL)
822			break;
823
824	       /*
825	        * Allocate memory as needed...
826		*/
827		if (qcount >= qalloc) {
828			qalloc += 16;
829
830			queue = SMB_REALLOC_ARRAY(queue, print_queue_struct, qalloc);
831
832			if (queue == NULL) {
833				DEBUG(0,("cups_queue_get: Not enough memory!"));
834				qcount = 0;
835				goto out;
836			}
837		}
838
839		temp = queue + qcount;
840		memset(temp, 0, sizeof(print_queue_struct));
841
842	       /*
843		* Pull the needed attributes from this job...
844		*/
845
846		job_id       = 0;
847		job_priority = 50;
848		job_status   = IPP_JOB_PENDING;
849		job_time     = 0;
850		job_k_octets = 0;
851		user_name    = NULL;
852		job_name     = NULL;
853
854		while (attr != NULL && attr->group_tag == IPP_TAG_JOB) {
855        		if (attr->name == NULL) {
856				attr = attr->next;
857				break;
858			}
859
860        		if (strcmp(attr->name, "job-id") == 0 &&
861			    attr->value_tag == IPP_TAG_INTEGER)
862				job_id = attr->values[0].integer;
863
864        		if (strcmp(attr->name, "job-k-octets") == 0 &&
865			    attr->value_tag == IPP_TAG_INTEGER)
866				job_k_octets = attr->values[0].integer;
867
868        		if (strcmp(attr->name, "job-priority") == 0 &&
869			    attr->value_tag == IPP_TAG_INTEGER)
870				job_priority = attr->values[0].integer;
871
872        		if (strcmp(attr->name, "job-state") == 0 &&
873			    attr->value_tag == IPP_TAG_ENUM)
874				job_status = (ipp_jstate_t)(attr->values[0].integer);
875
876        		if (strcmp(attr->name, "time-at-creation") == 0 &&
877			    attr->value_tag == IPP_TAG_INTEGER)
878				job_time = attr->values[0].integer;
879
880        		if (strcmp(attr->name, "job-name") == 0 &&
881			    attr->value_tag == IPP_TAG_NAME)
882				job_name = attr->values[0].string.text;
883
884        		if (strcmp(attr->name, "job-originating-user-name") == 0 &&
885			    attr->value_tag == IPP_TAG_NAME)
886				user_name = attr->values[0].string.text;
887
888        		attr = attr->next;
889		}
890
891	       /*
892		* See if we have everything needed...
893		*/
894
895		if (user_name == NULL || job_name == NULL || job_id == 0) {
896			if (attr == NULL)
897				break;
898			else
899				continue;
900		}
901
902		temp->job      = job_id;
903		temp->size     = job_k_octets * 1024;
904		temp->status   = job_status == IPP_JOB_PENDING ? LPQ_QUEUED :
905				 job_status == IPP_JOB_STOPPED ? LPQ_PAUSED :
906                                 job_status == IPP_JOB_HELD ? LPQ_PAUSED :
907			         LPQ_PRINTING;
908		temp->priority = job_priority;
909		temp->time     = job_time;
910		strncpy(temp->fs_user, user_name, sizeof(temp->fs_user) - 1);
911		strncpy(temp->fs_file, job_name, sizeof(temp->fs_file) - 1);
912
913		qcount ++;
914
915		if (attr == NULL)
916			break;
917	}
918
919	ippDelete(response);
920	response = NULL;
921
922       /*
923	* Build an IPP_GET_PRINTER_ATTRIBUTES request, which requires the
924	* following attributes:
925	*
926	*    attributes-charset
927	*    attributes-natural-language
928	*    requested-attributes
929	*    printer-uri
930	*/
931
932	request = ippNew();
933
934	request->request.op.operation_id = IPP_GET_PRINTER_ATTRIBUTES;
935	request->request.op.request_id   = 1;
936
937	ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
938                     "attributes-charset", NULL, cupsLangEncoding(language));
939
940	ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
941                     "attributes-natural-language", NULL, language->language);
942
943        ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
944	              "requested-attributes",
945		      (sizeof(pattrs) / sizeof(pattrs[0])),
946		      NULL, pattrs);
947
948	ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
949                     "printer-uri", NULL, uri);
950
951       /*
952	* Do the request and get back a response...
953	*/
954
955	if ((response = cupsDoRequest(http, request, "/")) == NULL) {
956		DEBUG(0,("Unable to get printer status for %s - %s\n", printername,
957			 ippErrorString(cupsLastError())));
958		*q = queue;
959		goto out;
960	}
961
962	if (response->request.status.status_code >= IPP_OK_CONFLICT) {
963		DEBUG(0,("Unable to get printer status for %s - %s\n", printername,
964			 ippErrorString(response->request.status.status_code)));
965		*q = queue;
966		goto out;
967	}
968
969       /*
970        * Get the current printer status and convert it to the SAMBA values.
971	*/
972
973        if ((attr = ippFindAttribute(response, "printer-state", IPP_TAG_ENUM)) != NULL) {
974		if (attr->values[0].integer == IPP_PRINTER_STOPPED)
975			status->status = LPSTAT_STOPPED;
976		else
977			status->status = LPSTAT_OK;
978	}
979
980        if ((attr = ippFindAttribute(response, "printer-state-message",
981	                             IPP_TAG_TEXT)) != NULL)
982	        fstrcpy(status->message, attr->values[0].string.text);
983
984       /*
985        * Return the job queue...
986	*/
987
988	*q = queue;
989
990 out:
991	if (response)
992		ippDelete(response);
993
994	if (language)
995		cupsLangFree(language);
996
997	if (http)
998		httpClose(http);
999
1000	return qcount;
1001}
1002
1003
1004/*
1005 * 'cups_queue_pause()' - Pause a print queue.
1006 */
1007
1008static int cups_queue_pause(int snum)
1009{
1010	int		ret = 1;		/* Return value */
1011	http_t		*http = NULL;		/* HTTP connection to server */
1012	ipp_t		*request = NULL,	/* IPP Request */
1013			*response = NULL;	/* IPP Response */
1014	cups_lang_t	*language = NULL;	/* Default language */
1015	char		uri[HTTP_MAX_URI]; /* printer-uri attribute */
1016
1017
1018	DEBUG(5,("cups_queue_pause(%d)\n", snum));
1019
1020	/*
1021	 * Make sure we don't ask for passwords...
1022	 */
1023
1024        cupsSetPasswordCB(cups_passwd_cb);
1025
1026	/*
1027	 * Try to connect to the server...
1028	 */
1029
1030	if ((http = cups_connect()) == NULL) {
1031		goto out;
1032	}
1033
1034	/*
1035	 * Build an IPP_PAUSE_PRINTER request, which requires the following
1036	 * attributes:
1037	 *
1038	 *    attributes-charset
1039	 *    attributes-natural-language
1040	 *    printer-uri
1041	 *    requesting-user-name
1042	 */
1043
1044	request = ippNew();
1045
1046	request->request.op.operation_id = IPP_PAUSE_PRINTER;
1047	request->request.op.request_id   = 1;
1048
1049	language = cupsLangDefault();
1050
1051	ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
1052        	     "attributes-charset", NULL, cupsLangEncoding(language));
1053
1054	ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
1055        	     "attributes-natural-language", NULL, language->language);
1056
1057	slprintf(uri, sizeof(uri) - 1, "ipp://localhost/printers/%s",
1058	         PRINTERNAME(snum));
1059
1060	ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, uri);
1061
1062	ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
1063        	     NULL, current_user_info.unix_name);
1064
1065       /*
1066	* Do the request and get back a response...
1067	*/
1068
1069	if ((response = cupsDoRequest(http, request, "/admin/")) != NULL) {
1070		if (response->request.status.status_code >= IPP_OK_CONFLICT) {
1071			DEBUG(0,("Unable to pause printer %s - %s\n", PRINTERNAME(snum),
1072				ippErrorString(cupsLastError())));
1073		} else {
1074			ret = 0;
1075		}
1076	} else {
1077		DEBUG(0,("Unable to pause printer %s - %s\n", PRINTERNAME(snum),
1078			ippErrorString(cupsLastError())));
1079	}
1080
1081 out:
1082	if (response)
1083		ippDelete(response);
1084
1085	if (language)
1086		cupsLangFree(language);
1087
1088	if (http)
1089		httpClose(http);
1090
1091	return ret;
1092}
1093
1094
1095/*
1096 * 'cups_queue_resume()' - Restart a print queue.
1097 */
1098
1099static int cups_queue_resume(int snum)
1100{
1101	int		ret = 1;		/* Return value */
1102	http_t		*http = NULL;		/* HTTP connection to server */
1103	ipp_t		*request = NULL,	/* IPP Request */
1104			*response = NULL;	/* IPP Response */
1105	cups_lang_t	*language = NULL;	/* Default language */
1106	char		uri[HTTP_MAX_URI]; /* printer-uri attribute */
1107
1108
1109	DEBUG(5,("cups_queue_resume(%d)\n", snum));
1110
1111       /*
1112        * Make sure we don't ask for passwords...
1113	*/
1114
1115        cupsSetPasswordCB(cups_passwd_cb);
1116
1117       /*
1118	* Try to connect to the server...
1119	*/
1120
1121	if ((http = cups_connect()) == NULL) {
1122		goto out;
1123	}
1124
1125       /*
1126	* Build an IPP_RESUME_PRINTER request, which requires the following
1127	* attributes:
1128	*
1129	*    attributes-charset
1130	*    attributes-natural-language
1131	*    printer-uri
1132	*    requesting-user-name
1133	*/
1134
1135	request = ippNew();
1136
1137	request->request.op.operation_id = IPP_RESUME_PRINTER;
1138	request->request.op.request_id   = 1;
1139
1140	language = cupsLangDefault();
1141
1142	ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
1143        	     "attributes-charset", NULL, cupsLangEncoding(language));
1144
1145	ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
1146        	     "attributes-natural-language", NULL, language->language);
1147
1148	slprintf(uri, sizeof(uri) - 1, "ipp://localhost/printers/%s",
1149	         PRINTERNAME(snum));
1150
1151	ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, uri);
1152
1153	ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
1154        	     NULL, current_user_info.unix_name);
1155
1156       /*
1157	* Do the request and get back a response...
1158	*/
1159
1160	if ((response = cupsDoRequest(http, request, "/admin/")) != NULL) {
1161		if (response->request.status.status_code >= IPP_OK_CONFLICT) {
1162			DEBUG(0,("Unable to resume printer %s - %s\n", PRINTERNAME(snum),
1163				ippErrorString(cupsLastError())));
1164		} else {
1165			ret = 0;
1166		}
1167	} else {
1168		DEBUG(0,("Unable to resume printer %s - %s\n", PRINTERNAME(snum),
1169			ippErrorString(cupsLastError())));
1170	}
1171
1172 out:
1173	if (response)
1174		ippDelete(response);
1175
1176	if (language)
1177		cupsLangFree(language);
1178
1179	if (http)
1180		httpClose(http);
1181
1182	return ret;
1183}
1184
1185/*******************************************************************
1186 * CUPS printing interface definitions...
1187 ******************************************************************/
1188
1189struct printif	cups_printif =
1190{
1191	PRINT_CUPS,
1192	cups_queue_get,
1193	cups_queue_pause,
1194	cups_queue_resume,
1195	cups_job_delete,
1196	cups_job_pause,
1197	cups_job_resume,
1198	cups_job_submit,
1199};
1200
1201BOOL cups_pull_comment_location(NT_PRINTER_INFO_LEVEL_2 *printer)
1202{
1203	http_t		*http = NULL;		/* HTTP connection to server */
1204	ipp_t		*request = NULL,	/* IPP Request */
1205			*response = NULL;	/* IPP Response */
1206	ipp_attribute_t	*attr;		/* Current attribute */
1207	cups_lang_t	*language = NULL;	/* Default language */
1208	char		*name,		/* printer-name attribute */
1209			*info,		/* printer-info attribute */
1210			*location;	/* printer-location attribute */
1211	char		uri[HTTP_MAX_URI];
1212	static const char *requested[] =/* Requested attributes */
1213			{
1214			  "printer-name",
1215			  "printer-info",
1216			  "printer-location"
1217			};
1218	BOOL ret = False;
1219
1220	DEBUG(5, ("pulling %s location\n", printer->sharename));
1221
1222	/*
1223	 * Make sure we don't ask for passwords...
1224	 */
1225
1226        cupsSetPasswordCB(cups_passwd_cb);
1227
1228	/*
1229	 * Try to connect to the server...
1230	 */
1231
1232	if ((http = cups_connect()) == NULL) {
1233		goto out;
1234	}
1235
1236	request = ippNew();
1237
1238	request->request.op.operation_id = IPP_GET_PRINTER_ATTRIBUTES;
1239	request->request.op.request_id   = 1;
1240
1241	language = cupsLangDefault();
1242
1243	ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
1244                     "attributes-charset", NULL, cupsLangEncoding(language));
1245
1246	ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
1247                     "attributes-natural-language", NULL, language->language);
1248
1249	slprintf(uri, sizeof(uri) - 1, "ipp://%s/printers/%s",
1250		 lp_cups_server(), printer->sharename);
1251
1252	ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
1253                     "printer-uri", NULL, uri);
1254
1255        ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
1256	              "requested-attributes",
1257		      (sizeof(requested) / sizeof(requested[0])),
1258		      NULL, requested);
1259
1260	/*
1261	 * Do the request and get back a response...
1262	 */
1263
1264	if ((response = cupsDoRequest(http, request, "/")) == NULL) {
1265		DEBUG(0,("Unable to get printer attributes - %s\n",
1266			 ippErrorString(cupsLastError())));
1267		goto out;
1268	}
1269
1270	for (attr = response->attrs; attr != NULL;) {
1271		/*
1272		 * Skip leading attributes until we hit a printer...
1273		 */
1274
1275		while (attr != NULL && attr->group_tag != IPP_TAG_PRINTER)
1276			attr = attr->next;
1277
1278		if (attr == NULL)
1279        		break;
1280
1281		/*
1282		 * Pull the needed attributes from this printer...
1283		 */
1284
1285		name       = NULL;
1286		info       = NULL;
1287		location   = NULL;
1288
1289		while ( attr && (attr->group_tag == IPP_TAG_PRINTER) ) {
1290			/* Grab the comment if we don't have one */
1291        		if ( (strcmp(attr->name, "printer-info") == 0)
1292			     && (attr->value_tag == IPP_TAG_TEXT)
1293			     && !strlen(printer->comment) )
1294			{
1295				DEBUG(5,("cups_pull_comment_location: Using cups comment: %s\n",
1296					 attr->values[0].string.text));
1297			    	pstrcpy(printer->comment,attr->values[0].string.text);
1298			}
1299
1300			/* Grab the location if we don't have one */
1301			if ( (strcmp(attr->name, "printer-location") == 0)
1302			     && (attr->value_tag == IPP_TAG_TEXT)
1303			     && !strlen(printer->location) )
1304			{
1305				DEBUG(5,("cups_pull_comment_location: Using cups location: %s\n",
1306					 attr->values[0].string.text));
1307			    	fstrcpy(printer->location,attr->values[0].string.text);
1308			}
1309
1310        		attr = attr->next;
1311		}
1312
1313		/*
1314		 * See if we have everything needed...
1315		 */
1316
1317		if (name == NULL)
1318			break;
1319
1320	}
1321
1322	ret = True;
1323
1324 out:
1325	if (response)
1326		ippDelete(response);
1327
1328	if (language)
1329		cupsLangFree(language);
1330
1331	if (http)
1332		httpClose(http);
1333
1334	return ret;
1335}
1336
1337#else
1338 /* this keeps fussy compilers happy */
1339 void print_cups_dummy(void);
1340 void print_cups_dummy(void) {}
1341#endif /* HAVE_CUPS */
1342