r4881: Varient of Lar's patch for #2270. Jerry promises to test :-).
[Samba/bb.git] / source / printing / print_cups.c
blobbe47f16408866e61f9daac2f9f3992220546ba9c
1 /*
2 * Support code for the Common UNIX Printing System ("CUPS")
4 * Copyright 1999-2003 by Michael R Sweet.
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.
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.
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.
21 #include "includes.h"
22 #include "printing.h"
24 #ifdef HAVE_CUPS
25 #include <cups/cups.h>
26 #include <cups/language.h>
30 * 'cups_passwd_cb()' - The CUPS password callback...
33 static const char * /* O - Password or NULL */
34 cups_passwd_cb(const char *prompt) /* I - Prompt */
37 * Always return NULL to indicate that no password is available...
40 return (NULL);
43 static const char *cups_server(void)
45 if ((lp_cups_server() != NULL) && (strlen(lp_cups_server()) > 0)) {
46 DEBUG(10, ("cups server explicitly set to %s\n",
47 lp_cups_server()));
48 return lp_cups_server();
51 DEBUG(10, ("cups server left to default %s\n", cupsServer()));
52 return cupsServer();
55 BOOL cups_cache_reload(void)
57 http_t *http = NULL; /* HTTP connection to server */
58 ipp_t *request = NULL, /* IPP Request */
59 *response = NULL; /* IPP Response */
60 ipp_attribute_t *attr; /* Current attribute */
61 cups_lang_t *language = NULL; /* Default language */
62 char *name, /* printer-name attribute */
63 *info; /* printer-info attribute */
64 static const char *requested[] =/* Requested attributes */
66 "printer-name",
67 "printer-info"
68 };
69 BOOL ret = False;
71 DEBUG(5, ("reloading cups printcap cache\n"));
74 * Make sure we don't ask for passwords...
77 cupsSetPasswordCB(cups_passwd_cb);
80 * Try to connect to the server...
83 if ((http = httpConnect(cups_server(), ippPort())) == NULL) {
84 DEBUG(0,("Unable to connect to CUPS server %s - %s\n",
85 cups_server(), strerror(errno)));
86 goto out;
90 * Build a CUPS_GET_PRINTERS request, which requires the following
91 * attributes:
93 * attributes-charset
94 * attributes-natural-language
95 * requested-attributes
98 request = ippNew();
100 request->request.op.operation_id = CUPS_GET_PRINTERS;
101 request->request.op.request_id = 1;
103 language = cupsLangDefault();
105 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
106 "attributes-charset", NULL, cupsLangEncoding(language));
108 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
109 "attributes-natural-language", NULL, language->language);
111 ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
112 "requested-attributes",
113 (sizeof(requested) / sizeof(requested[0])),
114 NULL, requested);
117 * Do the request and get back a response...
120 if ((response = cupsDoRequest(http, request, "/")) == NULL) {
121 DEBUG(0,("Unable to get printer list - %s\n",
122 ippErrorString(cupsLastError())));
123 goto out;
126 for (attr = response->attrs; attr != NULL;) {
128 * Skip leading attributes until we hit a printer...
131 while (attr != NULL && attr->group_tag != IPP_TAG_PRINTER)
132 attr = attr->next;
134 if (attr == NULL)
135 break;
138 * Pull the needed attributes from this printer...
141 name = NULL;
142 info = NULL;
144 while (attr != NULL && attr->group_tag == IPP_TAG_PRINTER) {
145 if (strcmp(attr->name, "printer-name") == 0 &&
146 attr->value_tag == IPP_TAG_NAME)
147 name = attr->values[0].string.text;
149 if (strcmp(attr->name, "printer-info") == 0 &&
150 attr->value_tag == IPP_TAG_TEXT)
151 info = attr->values[0].string.text;
153 attr = attr->next;
157 * See if we have everything needed...
160 if (name == NULL)
161 break;
163 if (!pcap_cache_add(name, info)) {
164 goto out;
168 ippDelete(response);
169 response = NULL;
172 * Build a CUPS_GET_CLASSES request, which requires the following
173 * attributes:
175 * attributes-charset
176 * attributes-natural-language
177 * requested-attributes
180 request->request.op.operation_id = CUPS_GET_CLASSES;
181 request->request.op.request_id = 1;
183 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
184 "attributes-charset", NULL, cupsLangEncoding(language));
186 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
187 "attributes-natural-language", NULL, language->language);
189 ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
190 "requested-attributes",
191 (sizeof(requested) / sizeof(requested[0])),
192 NULL, requested);
195 * Do the request and get back a response...
198 if ((response = cupsDoRequest(http, request, "/")) == NULL) {
199 DEBUG(0,("Unable to get printer list - %s\n",
200 ippErrorString(cupsLastError())));
201 goto out;
204 for (attr = response->attrs; attr != NULL;) {
206 * Skip leading attributes until we hit a printer...
209 while (attr != NULL && attr->group_tag != IPP_TAG_PRINTER)
210 attr = attr->next;
212 if (attr == NULL)
213 break;
216 * Pull the needed attributes from this printer...
219 name = NULL;
220 info = NULL;
222 while (attr != NULL && attr->group_tag == IPP_TAG_PRINTER) {
223 if (strcmp(attr->name, "printer-name") == 0 &&
224 attr->value_tag == IPP_TAG_NAME)
225 name = attr->values[0].string.text;
227 if (strcmp(attr->name, "printer-info") == 0 &&
228 attr->value_tag == IPP_TAG_TEXT)
229 info = attr->values[0].string.text;
231 attr = attr->next;
235 * See if we have everything needed...
238 if (name == NULL)
239 break;
241 if (!pcap_cache_add(name, info)) {
242 goto out;
246 ret = True;
248 out:
250 if (request)
251 ippDelete(request);
253 if (response)
254 ippDelete(response);
256 if (language)
257 cupsLangFree(language);
259 if (http)
260 httpClose(http);
262 return ret;
267 * 'cups_job_delete()' - Delete a job.
270 static int cups_job_delete(int snum, struct printjob *pjob)
272 int ret = 1; /* Return value */
273 http_t *http = NULL; /* HTTP connection to server */
274 ipp_t *request = NULL, /* IPP Request */
275 *response = NULL; /* IPP Response */
276 cups_lang_t *language = NULL; /* Default language */
277 char uri[HTTP_MAX_URI]; /* printer-uri attribute */
280 DEBUG(5,("cups_job_delete(%d, %p (%d))\n", snum, pjob, pjob->sysjob));
283 * Make sure we don't ask for passwords...
286 cupsSetPasswordCB(cups_passwd_cb);
289 * Try to connect to the server...
292 if ((http = httpConnect(cups_server(), ippPort())) == NULL) {
293 DEBUG(0,("Unable to connect to CUPS server %s - %s\n",
294 cups_server(), strerror(errno)));
295 goto out;
299 * Build an IPP_CANCEL_JOB request, which requires the following
300 * attributes:
302 * attributes-charset
303 * attributes-natural-language
304 * job-uri
305 * requesting-user-name
308 request = ippNew();
310 request->request.op.operation_id = IPP_CANCEL_JOB;
311 request->request.op.request_id = 1;
313 language = cupsLangDefault();
315 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
316 "attributes-charset", NULL, cupsLangEncoding(language));
318 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
319 "attributes-natural-language", NULL, language->language);
321 slprintf(uri, sizeof(uri) - 1, "ipp://localhost/jobs/%d", pjob->sysjob);
323 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri", NULL, uri);
325 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
326 NULL, pjob->user);
329 * Do the request and get back a response...
332 if ((response = cupsDoRequest(http, request, "/jobs")) != NULL) {
333 if (response->request.status.status_code >= IPP_OK_CONFLICT) {
334 DEBUG(0,("Unable to cancel job %d - %s\n", pjob->sysjob,
335 ippErrorString(cupsLastError())));
336 } else {
337 ret = 0;
339 } else {
340 DEBUG(0,("Unable to cancel job %d - %s\n", pjob->sysjob,
341 ippErrorString(cupsLastError())));
344 out:
346 if (request)
347 ippDelete(request);
349 if (response)
350 ippDelete(response);
352 if (language)
353 cupsLangFree(language);
355 if (http)
356 httpClose(http);
358 return ret;
363 * 'cups_job_pause()' - Pause a job.
366 static int cups_job_pause(int snum, struct printjob *pjob)
368 int ret = 1; /* Return value */
369 http_t *http = NULL; /* HTTP connection to server */
370 ipp_t *request = NULL, /* IPP Request */
371 *response = NULL; /* IPP Response */
372 cups_lang_t *language = NULL; /* Default language */
373 char uri[HTTP_MAX_URI]; /* printer-uri attribute */
376 DEBUG(5,("cups_job_pause(%d, %p (%d))\n", snum, pjob, pjob->sysjob));
379 * Make sure we don't ask for passwords...
382 cupsSetPasswordCB(cups_passwd_cb);
385 * Try to connect to the server...
388 if ((http = httpConnect(cups_server(), ippPort())) == NULL) {
389 DEBUG(0,("Unable to connect to CUPS server %s - %s\n",
390 cups_server(), strerror(errno)));
391 goto out;
395 * Build an IPP_HOLD_JOB request, which requires the following
396 * attributes:
398 * attributes-charset
399 * attributes-natural-language
400 * job-uri
401 * requesting-user-name
404 request = ippNew();
406 request->request.op.operation_id = IPP_HOLD_JOB;
407 request->request.op.request_id = 1;
409 language = cupsLangDefault();
411 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
412 "attributes-charset", NULL, cupsLangEncoding(language));
414 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
415 "attributes-natural-language", NULL, language->language);
417 slprintf(uri, sizeof(uri) - 1, "ipp://localhost/jobs/%d", pjob->sysjob);
419 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri", NULL, uri);
421 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
422 NULL, pjob->user);
425 * Do the request and get back a response...
428 if ((response = cupsDoRequest(http, request, "/jobs")) != NULL) {
429 if (response->request.status.status_code >= IPP_OK_CONFLICT) {
430 DEBUG(0,("Unable to hold job %d - %s\n", pjob->sysjob,
431 ippErrorString(cupsLastError())));
432 } else {
433 ret = 0;
435 } else {
436 DEBUG(0,("Unable to hold job %d - %s\n", pjob->sysjob,
437 ippErrorString(cupsLastError())));
440 out:
442 if (request)
443 ippDelete(request);
445 if (response)
446 ippDelete(response);
448 if (language)
449 cupsLangFree(language);
451 if (http)
452 httpClose(http);
454 return ret;
459 * 'cups_job_resume()' - Resume a paused job.
462 static int cups_job_resume(int snum, struct printjob *pjob)
464 int ret = 1; /* Return value */
465 http_t *http = NULL; /* HTTP connection to server */
466 ipp_t *request = NULL, /* IPP Request */
467 *response = NULL; /* IPP Response */
468 cups_lang_t *language = NULL; /* Default language */
469 char uri[HTTP_MAX_URI]; /* printer-uri attribute */
472 DEBUG(5,("cups_job_resume(%d, %p (%d))\n", snum, pjob, pjob->sysjob));
475 * Make sure we don't ask for passwords...
478 cupsSetPasswordCB(cups_passwd_cb);
481 * Try to connect to the server...
484 if ((http = httpConnect(cups_server(), ippPort())) == NULL) {
485 DEBUG(0,("Unable to connect to CUPS server %s - %s\n",
486 cups_server(), strerror(errno)));
487 goto out;
491 * Build an IPP_RELEASE_JOB request, which requires the following
492 * attributes:
494 * attributes-charset
495 * attributes-natural-language
496 * job-uri
497 * requesting-user-name
500 request = ippNew();
502 request->request.op.operation_id = IPP_RELEASE_JOB;
503 request->request.op.request_id = 1;
505 language = cupsLangDefault();
507 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
508 "attributes-charset", NULL, cupsLangEncoding(language));
510 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
511 "attributes-natural-language", NULL, language->language);
513 slprintf(uri, sizeof(uri) - 1, "ipp://localhost/jobs/%d", pjob->sysjob);
515 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri", NULL, uri);
517 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
518 NULL, pjob->user);
521 * Do the request and get back a response...
524 if ((response = cupsDoRequest(http, request, "/jobs")) != NULL) {
525 if (response->request.status.status_code >= IPP_OK_CONFLICT) {
526 DEBUG(0,("Unable to release job %d - %s\n", pjob->sysjob,
527 ippErrorString(cupsLastError())));
528 } else {
529 ret = 0;
531 } else {
532 DEBUG(0,("Unable to release job %d - %s\n", pjob->sysjob,
533 ippErrorString(cupsLastError())));
536 out:
538 if (request)
539 ippDelete(request);
541 if (response)
542 ippDelete(response);
544 if (language)
545 cupsLangFree(language);
547 if (http)
548 httpClose(http);
550 return ret;
555 * 'cups_job_submit()' - Submit a job for printing.
558 static int cups_job_submit(int snum, struct printjob *pjob)
560 int ret = 1; /* Return value */
561 http_t *http = NULL; /* HTTP connection to server */
562 ipp_t *request = NULL, /* IPP Request */
563 *response = NULL; /* IPP Response */
564 cups_lang_t *language = NULL; /* Default language */
565 char uri[HTTP_MAX_URI]; /* printer-uri attribute */
566 char *clientname = NULL; /* hostname of client for job-originating-host attribute */
567 pstring new_jobname;
568 int num_options = 0;
569 cups_option_t *options = NULL;
571 DEBUG(5,("cups_job_submit(%d, %p (%d))\n", snum, pjob, pjob->sysjob));
574 * Make sure we don't ask for passwords...
577 cupsSetPasswordCB(cups_passwd_cb);
580 * Try to connect to the server...
583 if ((http = httpConnect(cups_server(), ippPort())) == NULL) {
584 DEBUG(0,("Unable to connect to CUPS server %s - %s\n",
585 cups_server(), strerror(errno)));
586 goto out;
590 * Build an IPP_PRINT_JOB request, which requires the following
591 * attributes:
593 * attributes-charset
594 * attributes-natural-language
595 * printer-uri
596 * requesting-user-name
597 * [document-data]
600 request = ippNew();
602 request->request.op.operation_id = IPP_PRINT_JOB;
603 request->request.op.request_id = 1;
605 language = cupsLangDefault();
607 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
608 "attributes-charset", NULL, cupsLangEncoding(language));
610 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
611 "attributes-natural-language", NULL, language->language);
613 slprintf(uri, sizeof(uri) - 1, "ipp://localhost/printers/%s",
614 PRINTERNAME(snum));
616 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
617 "printer-uri", NULL, uri);
619 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
620 NULL, pjob->user);
622 clientname = client_name();
623 if (strcmp(clientname, "UNKNOWN") == 0) {
624 clientname = client_addr();
627 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
628 "job-originating-host-name", NULL,
629 clientname);
631 pstr_sprintf(new_jobname,"%s%.8u %s", PRINT_SPOOL_PREFIX,
632 (unsigned int)pjob->smbjob, pjob->jobname);
634 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "job-name", NULL,
635 new_jobname);
638 * add any options defined in smb.conf
641 num_options = 0;
642 options = NULL;
643 num_options = cupsParseOptions(lp_cups_options(snum), num_options, &options);
645 if ( num_options )
646 cupsEncodeOptions(request, num_options, options);
649 * Do the request and get back a response...
652 slprintf(uri, sizeof(uri) - 1, "/printers/%s", PRINTERNAME(snum));
654 if ((response = cupsDoFileRequest(http, request, uri, pjob->filename)) != NULL) {
655 if (response->request.status.status_code >= IPP_OK_CONFLICT) {
656 DEBUG(0,("Unable to print file to %s - %s\n", PRINTERNAME(snum),
657 ippErrorString(cupsLastError())));
658 } else {
659 ret = 0;
661 } else {
662 DEBUG(0,("Unable to print file to `%s' - %s\n", PRINTERNAME(snum),
663 ippErrorString(cupsLastError())));
666 if ( ret == 0 )
667 unlink(pjob->filename);
668 /* else print_job_end will do it for us */
670 out:
672 if (request)
673 ippDelete(request);
675 if (response)
676 ippDelete(response);
678 if (language)
679 cupsLangFree(language);
681 if (http)
682 httpClose(http);
684 return ret;
685 return (ret);
689 * 'cups_queue_get()' - Get all the jobs in the print queue.
692 static int cups_queue_get(const char *printer_name,
693 enum printing_types printing_type,
694 char *lpq_command,
695 print_queue_struct **q,
696 print_status_struct *status)
698 http_t *http = NULL; /* HTTP connection to server */
699 ipp_t *request = NULL, /* IPP Request */
700 *response = NULL; /* IPP Response */
701 ipp_attribute_t *attr = NULL; /* Current attribute */
702 cups_lang_t *language = NULL; /* Default language */
703 char uri[HTTP_MAX_URI]; /* printer-uri attribute */
704 int qcount = 0, /* Number of active queue entries */
705 qalloc = 0; /* Number of queue entries allocated */
706 print_queue_struct *queue = NULL, /* Queue entries */
707 *temp; /* Temporary pointer for queue */
708 const char *user_name, /* job-originating-user-name attribute */
709 *job_name; /* job-name attribute */
710 int job_id; /* job-id attribute */
711 int job_k_octets; /* job-k-octets attribute */
712 time_t job_time; /* time-at-creation attribute */
713 ipp_jstate_t job_status; /* job-status attribute */
714 int job_priority; /* job-priority attribute */
715 static const char *jattrs[] = /* Requested job attributes */
717 "job-id",
718 "job-k-octets",
719 "job-name",
720 "job-originating-user-name",
721 "job-priority",
722 "job-state",
723 "time-at-creation",
725 static const char *pattrs[] = /* Requested printer attributes */
727 "printer-state",
728 "printer-state-message"
731 *q = NULL;
733 DEBUG(5,("cups_queue_get(%s, %p, %p)\n", printer_name, q, status));
736 * Make sure we don't ask for passwords...
739 cupsSetPasswordCB(cups_passwd_cb);
742 * Try to connect to the server...
745 if ((http = httpConnect(cups_server(), ippPort())) == NULL) {
746 DEBUG(0,("Unable to connect to CUPS server %s - %s\n",
747 cups_server(), strerror(errno)));
748 goto out;
752 * Generate the printer URI...
755 slprintf(uri, sizeof(uri) - 1, "ipp://localhost/printers/%s", printer_name);
758 * Build an IPP_GET_JOBS request, which requires the following
759 * attributes:
761 * attributes-charset
762 * attributes-natural-language
763 * requested-attributes
764 * printer-uri
767 request = ippNew();
769 request->request.op.operation_id = IPP_GET_JOBS;
770 request->request.op.request_id = 1;
772 language = cupsLangDefault();
774 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
775 "attributes-charset", NULL, cupsLangEncoding(language));
777 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
778 "attributes-natural-language", NULL, language->language);
780 ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
781 "requested-attributes",
782 (sizeof(jattrs) / sizeof(jattrs[0])),
783 NULL, jattrs);
785 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
786 "printer-uri", NULL, uri);
789 * Do the request and get back a response...
792 if ((response = cupsDoRequest(http, request, "/")) == NULL) {
793 DEBUG(0,("Unable to get jobs for %s - %s\n", uri,
794 ippErrorString(cupsLastError())));
795 goto out;
798 if (response->request.status.status_code >= IPP_OK_CONFLICT) {
799 DEBUG(0,("Unable to get jobs for %s - %s\n", uri,
800 ippErrorString(response->request.status.status_code)));
801 goto out;
805 * Process the jobs...
808 qcount = 0;
809 qalloc = 0;
810 queue = NULL;
812 for (attr = response->attrs; attr != NULL; attr = attr->next) {
814 * Skip leading attributes until we hit a job...
817 while (attr != NULL && attr->group_tag != IPP_TAG_JOB)
818 attr = attr->next;
820 if (attr == NULL)
821 break;
824 * Allocate memory as needed...
826 if (qcount >= qalloc) {
827 qalloc += 16;
829 temp = SMB_REALLOC_ARRAY(queue, print_queue_struct, qalloc);
831 if (temp == NULL) {
832 DEBUG(0,("cups_queue_get: Not enough memory!"));
833 qcount = 0;
834 SAFE_FREE(queue);
835 goto out;
838 queue = temp;
841 temp = queue + qcount;
842 memset(temp, 0, sizeof(print_queue_struct));
845 * Pull the needed attributes from this job...
848 job_id = 0;
849 job_priority = 50;
850 job_status = IPP_JOB_PENDING;
851 job_time = 0;
852 job_k_octets = 0;
853 user_name = NULL;
854 job_name = NULL;
856 while (attr != NULL && attr->group_tag == IPP_TAG_JOB) {
857 if (attr->name == NULL) {
858 attr = attr->next;
859 break;
862 if (strcmp(attr->name, "job-id") == 0 &&
863 attr->value_tag == IPP_TAG_INTEGER)
864 job_id = attr->values[0].integer;
866 if (strcmp(attr->name, "job-k-octets") == 0 &&
867 attr->value_tag == IPP_TAG_INTEGER)
868 job_k_octets = attr->values[0].integer;
870 if (strcmp(attr->name, "job-priority") == 0 &&
871 attr->value_tag == IPP_TAG_INTEGER)
872 job_priority = attr->values[0].integer;
874 if (strcmp(attr->name, "job-state") == 0 &&
875 attr->value_tag == IPP_TAG_ENUM)
876 job_status = (ipp_jstate_t)(attr->values[0].integer);
878 if (strcmp(attr->name, "time-at-creation") == 0 &&
879 attr->value_tag == IPP_TAG_INTEGER)
880 job_time = attr->values[0].integer;
882 if (strcmp(attr->name, "job-name") == 0 &&
883 attr->value_tag == IPP_TAG_NAME)
884 job_name = attr->values[0].string.text;
886 if (strcmp(attr->name, "job-originating-user-name") == 0 &&
887 attr->value_tag == IPP_TAG_NAME)
888 user_name = attr->values[0].string.text;
890 attr = attr->next;
894 * See if we have everything needed...
897 if (user_name == NULL || job_name == NULL || job_id == 0) {
898 if (attr == NULL)
899 break;
900 else
901 continue;
904 temp->job = job_id;
905 temp->size = job_k_octets * 1024;
906 temp->status = job_status == IPP_JOB_PENDING ? LPQ_QUEUED :
907 job_status == IPP_JOB_STOPPED ? LPQ_PAUSED :
908 job_status == IPP_JOB_HELD ? LPQ_PAUSED :
909 LPQ_PRINTING;
910 temp->priority = job_priority;
911 temp->time = job_time;
912 strncpy(temp->fs_user, user_name, sizeof(temp->fs_user) - 1);
913 strncpy(temp->fs_file, job_name, sizeof(temp->fs_file) - 1);
915 qcount ++;
917 if (attr == NULL)
918 break;
921 ippDelete(response);
922 response = NULL;
925 * Build an IPP_GET_PRINTER_ATTRIBUTES request, which requires the
926 * following attributes:
928 * attributes-charset
929 * attributes-natural-language
930 * requested-attributes
931 * printer-uri
934 request->request.op.operation_id = IPP_GET_PRINTER_ATTRIBUTES;
935 request->request.op.request_id = 1;
937 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
938 "attributes-charset", NULL, cupsLangEncoding(language));
940 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
941 "attributes-natural-language", NULL, language->language);
943 ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
944 "requested-attributes",
945 (sizeof(pattrs) / sizeof(pattrs[0])),
946 NULL, pattrs);
948 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
949 "printer-uri", NULL, uri);
952 * Do the request and get back a response...
955 if ((response = cupsDoRequest(http, request, "/")) == NULL) {
956 DEBUG(0,("Unable to get printer status for %s - %s\n", printer_name,
957 ippErrorString(cupsLastError())));
958 *q = queue;
959 goto out;
962 if (response->request.status.status_code >= IPP_OK_CONFLICT) {
963 DEBUG(0,("Unable to get printer status for %s - %s\n", printer_name,
964 ippErrorString(response->request.status.status_code)));
965 *q = queue;
966 goto out;
970 * Get the current printer status and convert it to the SAMBA values.
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;
980 if ((attr = ippFindAttribute(response, "printer-state-message",
981 IPP_TAG_TEXT)) != NULL)
982 fstrcpy(status->message, attr->values[0].string.text);
985 * Return the job queue...
988 *q = queue;
990 out:
992 if (request)
993 ippDelete(request);
995 if (response)
996 ippDelete(response);
998 if (language)
999 cupsLangFree(language);
1001 if (http)
1002 httpClose(http);
1004 return qcount;
1009 * 'cups_queue_pause()' - Pause a print queue.
1012 static int cups_queue_pause(int snum)
1014 extern userdom_struct current_user_info;
1015 int ret = 1; /* Return value */
1016 http_t *http = NULL; /* HTTP connection to server */
1017 ipp_t *request = NULL, /* IPP Request */
1018 *response = NULL; /* IPP Response */
1019 cups_lang_t *language = NULL; /* Default language */
1020 char uri[HTTP_MAX_URI]; /* printer-uri attribute */
1023 DEBUG(5,("cups_queue_pause(%d)\n", snum));
1026 * Make sure we don't ask for passwords...
1029 cupsSetPasswordCB(cups_passwd_cb);
1032 * Try to connect to the server...
1035 if ((http = httpConnect(cups_server(), ippPort())) == NULL) {
1036 DEBUG(0,("Unable to connect to CUPS server %s - %s\n",
1037 cups_server(), strerror(errno)));
1038 goto out;
1042 * Build an IPP_PAUSE_PRINTER request, which requires the following
1043 * attributes:
1045 * attributes-charset
1046 * attributes-natural-language
1047 * printer-uri
1048 * requesting-user-name
1051 request = ippNew();
1053 request->request.op.operation_id = IPP_PAUSE_PRINTER;
1054 request->request.op.request_id = 1;
1056 language = cupsLangDefault();
1058 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
1059 "attributes-charset", NULL, cupsLangEncoding(language));
1061 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
1062 "attributes-natural-language", NULL, language->language);
1064 slprintf(uri, sizeof(uri) - 1, "ipp://localhost/printers/%s",
1065 PRINTERNAME(snum));
1067 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, uri);
1069 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
1070 NULL, current_user_info.unix_name);
1073 * Do the request and get back a response...
1076 if ((response = cupsDoRequest(http, request, "/admin/")) != NULL) {
1077 if (response->request.status.status_code >= IPP_OK_CONFLICT) {
1078 DEBUG(0,("Unable to pause printer %s - %s\n", PRINTERNAME(snum),
1079 ippErrorString(cupsLastError())));
1080 } else {
1081 ret = 0;
1083 } else {
1084 DEBUG(0,("Unable to pause printer %s - %s\n", PRINTERNAME(snum),
1085 ippErrorString(cupsLastError())));
1088 out:
1090 if (request)
1091 ippDelete(request);
1093 if (response)
1094 ippDelete(response);
1096 if (language)
1097 cupsLangFree(language);
1099 if (http)
1100 httpClose(http);
1102 return ret;
1107 * 'cups_queue_resume()' - Restart a print queue.
1110 static int cups_queue_resume(int snum)
1112 extern userdom_struct current_user_info;
1113 int ret = 1; /* Return value */
1114 http_t *http = NULL; /* HTTP connection to server */
1115 ipp_t *request = NULL, /* IPP Request */
1116 *response = NULL; /* IPP Response */
1117 cups_lang_t *language = NULL; /* Default language */
1118 char uri[HTTP_MAX_URI]; /* printer-uri attribute */
1121 DEBUG(5,("cups_queue_resume(%d)\n", snum));
1124 * Make sure we don't ask for passwords...
1127 cupsSetPasswordCB(cups_passwd_cb);
1130 * Try to connect to the server...
1133 if ((http = httpConnect(cups_server(), ippPort())) == NULL) {
1134 DEBUG(0,("Unable to connect to CUPS server %s - %s\n",
1135 cups_server(), strerror(errno)));
1136 goto out;
1140 * Build an IPP_RESUME_PRINTER request, which requires the following
1141 * attributes:
1143 * attributes-charset
1144 * attributes-natural-language
1145 * printer-uri
1146 * requesting-user-name
1149 request = ippNew();
1151 request->request.op.operation_id = IPP_RESUME_PRINTER;
1152 request->request.op.request_id = 1;
1154 language = cupsLangDefault();
1156 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
1157 "attributes-charset", NULL, cupsLangEncoding(language));
1159 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
1160 "attributes-natural-language", NULL, language->language);
1162 slprintf(uri, sizeof(uri) - 1, "ipp://localhost/printers/%s",
1163 PRINTERNAME(snum));
1165 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, uri);
1167 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
1168 NULL, current_user_info.unix_name);
1171 * Do the request and get back a response...
1174 if ((response = cupsDoRequest(http, request, "/admin/")) != NULL) {
1175 if (response->request.status.status_code >= IPP_OK_CONFLICT) {
1176 DEBUG(0,("Unable to resume printer %s - %s\n", PRINTERNAME(snum),
1177 ippErrorString(cupsLastError())));
1178 } else {
1179 ret = 0;
1181 } else {
1182 DEBUG(0,("Unable to resume printer %s - %s\n", PRINTERNAME(snum),
1183 ippErrorString(cupsLastError())));
1186 out:
1188 if (request)
1189 ippDelete(request);
1191 if (response)
1192 ippDelete(response);
1194 if (language)
1195 cupsLangFree(language);
1197 if (http)
1198 httpClose(http);
1200 return ret;
1203 /*******************************************************************
1204 * CUPS printing interface definitions...
1205 ******************************************************************/
1207 struct printif cups_printif =
1209 PRINT_CUPS,
1210 cups_queue_get,
1211 cups_queue_pause,
1212 cups_queue_resume,
1213 cups_job_delete,
1214 cups_job_pause,
1215 cups_job_resume,
1216 cups_job_submit,
1219 #else
1220 /* this keeps fussy compilers happy */
1221 void print_cups_dummy(void) {}
1222 #endif /* HAVE_CUPS */