r5555: current with 3.0 tree as of r5548; getting ready for 3.0.12pre1
[Samba.git] / source / printing / print_cups.c
blobe6064564dc81589c68e4de7e47f573a9548aa7eb
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 = ippNew();
182 request->request.op.operation_id = CUPS_GET_CLASSES;
183 request->request.op.request_id = 1;
185 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
186 "attributes-charset", NULL, cupsLangEncoding(language));
188 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
189 "attributes-natural-language", NULL, language->language);
191 ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
192 "requested-attributes",
193 (sizeof(requested) / sizeof(requested[0])),
194 NULL, requested);
197 * Do the request and get back a response...
200 if ((response = cupsDoRequest(http, request, "/")) == NULL) {
201 DEBUG(0,("Unable to get printer list - %s\n",
202 ippErrorString(cupsLastError())));
203 goto out;
206 for (attr = response->attrs; attr != NULL;) {
208 * Skip leading attributes until we hit a printer...
211 while (attr != NULL && attr->group_tag != IPP_TAG_PRINTER)
212 attr = attr->next;
214 if (attr == NULL)
215 break;
218 * Pull the needed attributes from this printer...
221 name = NULL;
222 info = NULL;
224 while (attr != NULL && attr->group_tag == IPP_TAG_PRINTER) {
225 if (strcmp(attr->name, "printer-name") == 0 &&
226 attr->value_tag == IPP_TAG_NAME)
227 name = attr->values[0].string.text;
229 if (strcmp(attr->name, "printer-info") == 0 &&
230 attr->value_tag == IPP_TAG_TEXT)
231 info = attr->values[0].string.text;
233 attr = attr->next;
237 * See if we have everything needed...
240 if (name == NULL)
241 break;
243 if (!pcap_cache_add(name, info)) {
244 goto out;
248 ret = True;
250 out:
251 if (response)
252 ippDelete(response);
254 if (language)
255 cupsLangFree(language);
257 if (http)
258 httpClose(http);
260 return ret;
265 * 'cups_job_delete()' - Delete a job.
268 static int cups_job_delete(int snum, struct printjob *pjob)
270 int ret = 1; /* Return value */
271 http_t *http = NULL; /* HTTP connection to server */
272 ipp_t *request = NULL, /* IPP Request */
273 *response = NULL; /* IPP Response */
274 cups_lang_t *language = NULL; /* Default language */
275 char uri[HTTP_MAX_URI]; /* printer-uri attribute */
278 DEBUG(5,("cups_job_delete(%d, %p (%d))\n", snum, pjob, pjob->sysjob));
281 * Make sure we don't ask for passwords...
284 cupsSetPasswordCB(cups_passwd_cb);
287 * Try to connect to the server...
290 if ((http = httpConnect(cups_server(), ippPort())) == NULL) {
291 DEBUG(0,("Unable to connect to CUPS server %s - %s\n",
292 cups_server(), strerror(errno)));
293 goto out;
297 * Build an IPP_CANCEL_JOB request, which requires the following
298 * attributes:
300 * attributes-charset
301 * attributes-natural-language
302 * job-uri
303 * requesting-user-name
306 request = ippNew();
308 request->request.op.operation_id = IPP_CANCEL_JOB;
309 request->request.op.request_id = 1;
311 language = cupsLangDefault();
313 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
314 "attributes-charset", NULL, cupsLangEncoding(language));
316 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
317 "attributes-natural-language", NULL, language->language);
319 slprintf(uri, sizeof(uri) - 1, "ipp://localhost/jobs/%d", pjob->sysjob);
321 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri", NULL, uri);
323 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
324 NULL, pjob->user);
327 * Do the request and get back a response...
330 if ((response = cupsDoRequest(http, request, "/jobs")) != NULL) {
331 if (response->request.status.status_code >= IPP_OK_CONFLICT) {
332 DEBUG(0,("Unable to cancel job %d - %s\n", pjob->sysjob,
333 ippErrorString(cupsLastError())));
334 } else {
335 ret = 0;
337 } else {
338 DEBUG(0,("Unable to cancel job %d - %s\n", pjob->sysjob,
339 ippErrorString(cupsLastError())));
342 out:
343 if (response)
344 ippDelete(response);
346 if (language)
347 cupsLangFree(language);
349 if (http)
350 httpClose(http);
352 return ret;
357 * 'cups_job_pause()' - Pause a job.
360 static int cups_job_pause(int snum, struct printjob *pjob)
362 int ret = 1; /* Return value */
363 http_t *http = NULL; /* HTTP connection to server */
364 ipp_t *request = NULL, /* IPP Request */
365 *response = NULL; /* IPP Response */
366 cups_lang_t *language = NULL; /* Default language */
367 char uri[HTTP_MAX_URI]; /* printer-uri attribute */
370 DEBUG(5,("cups_job_pause(%d, %p (%d))\n", snum, pjob, pjob->sysjob));
373 * Make sure we don't ask for passwords...
376 cupsSetPasswordCB(cups_passwd_cb);
379 * Try to connect to the server...
382 if ((http = httpConnect(cups_server(), ippPort())) == NULL) {
383 DEBUG(0,("Unable to connect to CUPS server %s - %s\n",
384 cups_server(), strerror(errno)));
385 goto out;
389 * Build an IPP_HOLD_JOB request, which requires the following
390 * attributes:
392 * attributes-charset
393 * attributes-natural-language
394 * job-uri
395 * requesting-user-name
398 request = ippNew();
400 request->request.op.operation_id = IPP_HOLD_JOB;
401 request->request.op.request_id = 1;
403 language = cupsLangDefault();
405 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
406 "attributes-charset", NULL, cupsLangEncoding(language));
408 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
409 "attributes-natural-language", NULL, language->language);
411 slprintf(uri, sizeof(uri) - 1, "ipp://localhost/jobs/%d", pjob->sysjob);
413 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri", NULL, uri);
415 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
416 NULL, pjob->user);
419 * Do the request and get back a response...
422 if ((response = cupsDoRequest(http, request, "/jobs")) != NULL) {
423 if (response->request.status.status_code >= IPP_OK_CONFLICT) {
424 DEBUG(0,("Unable to hold job %d - %s\n", pjob->sysjob,
425 ippErrorString(cupsLastError())));
426 } else {
427 ret = 0;
429 } else {
430 DEBUG(0,("Unable to hold job %d - %s\n", pjob->sysjob,
431 ippErrorString(cupsLastError())));
434 out:
435 if (response)
436 ippDelete(response);
438 if (language)
439 cupsLangFree(language);
441 if (http)
442 httpClose(http);
444 return ret;
449 * 'cups_job_resume()' - Resume a paused job.
452 static int cups_job_resume(int snum, struct printjob *pjob)
454 int ret = 1; /* Return value */
455 http_t *http = NULL; /* HTTP connection to server */
456 ipp_t *request = NULL, /* IPP Request */
457 *response = NULL; /* IPP Response */
458 cups_lang_t *language = NULL; /* Default language */
459 char uri[HTTP_MAX_URI]; /* printer-uri attribute */
462 DEBUG(5,("cups_job_resume(%d, %p (%d))\n", snum, pjob, pjob->sysjob));
465 * Make sure we don't ask for passwords...
468 cupsSetPasswordCB(cups_passwd_cb);
471 * Try to connect to the server...
474 if ((http = httpConnect(cups_server(), ippPort())) == NULL) {
475 DEBUG(0,("Unable to connect to CUPS server %s - %s\n",
476 cups_server(), strerror(errno)));
477 goto out;
481 * Build an IPP_RELEASE_JOB request, which requires the following
482 * attributes:
484 * attributes-charset
485 * attributes-natural-language
486 * job-uri
487 * requesting-user-name
490 request = ippNew();
492 request->request.op.operation_id = IPP_RELEASE_JOB;
493 request->request.op.request_id = 1;
495 language = cupsLangDefault();
497 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
498 "attributes-charset", NULL, cupsLangEncoding(language));
500 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
501 "attributes-natural-language", NULL, language->language);
503 slprintf(uri, sizeof(uri) - 1, "ipp://localhost/jobs/%d", pjob->sysjob);
505 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri", NULL, uri);
507 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
508 NULL, pjob->user);
511 * Do the request and get back a response...
514 if ((response = cupsDoRequest(http, request, "/jobs")) != NULL) {
515 if (response->request.status.status_code >= IPP_OK_CONFLICT) {
516 DEBUG(0,("Unable to release job %d - %s\n", pjob->sysjob,
517 ippErrorString(cupsLastError())));
518 } else {
519 ret = 0;
521 } else {
522 DEBUG(0,("Unable to release job %d - %s\n", pjob->sysjob,
523 ippErrorString(cupsLastError())));
526 out:
527 if (response)
528 ippDelete(response);
530 if (language)
531 cupsLangFree(language);
533 if (http)
534 httpClose(http);
536 return ret;
541 * 'cups_job_submit()' - Submit a job for printing.
544 static int cups_job_submit(int snum, struct printjob *pjob)
546 int ret = 1; /* Return value */
547 http_t *http = NULL; /* HTTP connection to server */
548 ipp_t *request = NULL, /* IPP Request */
549 *response = NULL; /* IPP Response */
550 cups_lang_t *language = NULL; /* Default language */
551 char uri[HTTP_MAX_URI]; /* printer-uri attribute */
552 char *clientname = NULL; /* hostname of client for job-originating-host attribute */
553 pstring new_jobname;
554 int num_options = 0;
555 cups_option_t *options = NULL;
557 DEBUG(5,("cups_job_submit(%d, %p (%d))\n", snum, pjob, pjob->sysjob));
560 * Make sure we don't ask for passwords...
563 cupsSetPasswordCB(cups_passwd_cb);
566 * Try to connect to the server...
569 if ((http = httpConnect(cups_server(), ippPort())) == NULL) {
570 DEBUG(0,("Unable to connect to CUPS server %s - %s\n",
571 cups_server(), strerror(errno)));
572 goto out;
576 * Build an IPP_PRINT_JOB request, which requires the following
577 * attributes:
579 * attributes-charset
580 * attributes-natural-language
581 * printer-uri
582 * requesting-user-name
583 * [document-data]
586 request = ippNew();
588 request->request.op.operation_id = IPP_PRINT_JOB;
589 request->request.op.request_id = 1;
591 language = cupsLangDefault();
593 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
594 "attributes-charset", NULL, cupsLangEncoding(language));
596 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
597 "attributes-natural-language", NULL, language->language);
599 slprintf(uri, sizeof(uri) - 1, "ipp://localhost/printers/%s",
600 PRINTERNAME(snum));
602 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
603 "printer-uri", NULL, uri);
605 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
606 NULL, pjob->user);
608 clientname = client_name();
609 if (strcmp(clientname, "UNKNOWN") == 0) {
610 clientname = client_addr();
613 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
614 "job-originating-host-name", NULL,
615 clientname);
617 pstr_sprintf(new_jobname,"%s%.8u %s", PRINT_SPOOL_PREFIX,
618 (unsigned int)pjob->smbjob, pjob->jobname);
620 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "job-name", NULL,
621 new_jobname);
624 * add any options defined in smb.conf
627 num_options = 0;
628 options = NULL;
629 num_options = cupsParseOptions(lp_cups_options(snum), num_options, &options);
631 if ( num_options )
632 cupsEncodeOptions(request, num_options, options);
635 * Do the request and get back a response...
638 slprintf(uri, sizeof(uri) - 1, "/printers/%s", PRINTERNAME(snum));
640 if ((response = cupsDoFileRequest(http, request, uri, pjob->filename)) != NULL) {
641 if (response->request.status.status_code >= IPP_OK_CONFLICT) {
642 DEBUG(0,("Unable to print file to %s - %s\n", PRINTERNAME(snum),
643 ippErrorString(cupsLastError())));
644 } else {
645 ret = 0;
647 } else {
648 DEBUG(0,("Unable to print file to `%s' - %s\n", PRINTERNAME(snum),
649 ippErrorString(cupsLastError())));
652 if ( ret == 0 )
653 unlink(pjob->filename);
654 /* else print_job_end will do it for us */
656 out:
657 if (response)
658 ippDelete(response);
660 if (language)
661 cupsLangFree(language);
663 if (http)
664 httpClose(http);
666 return ret;
670 * 'cups_queue_get()' - Get all the jobs in the print queue.
673 static int cups_queue_get(const char *sharename,
674 enum printing_types printing_type,
675 char *lpq_command,
676 print_queue_struct **q,
677 print_status_struct *status)
679 fstring printername;
680 http_t *http = NULL; /* HTTP connection to server */
681 ipp_t *request = NULL, /* IPP Request */
682 *response = NULL; /* IPP Response */
683 ipp_attribute_t *attr = NULL; /* Current attribute */
684 cups_lang_t *language = NULL; /* Default language */
685 char uri[HTTP_MAX_URI]; /* printer-uri attribute */
686 int qcount = 0, /* Number of active queue entries */
687 qalloc = 0; /* Number of queue entries allocated */
688 print_queue_struct *queue = NULL, /* Queue entries */
689 *temp; /* Temporary pointer for queue */
690 const char *user_name, /* job-originating-user-name attribute */
691 *job_name; /* job-name attribute */
692 int job_id; /* job-id attribute */
693 int job_k_octets; /* job-k-octets attribute */
694 time_t job_time; /* time-at-creation attribute */
695 ipp_jstate_t job_status; /* job-status attribute */
696 int job_priority; /* job-priority attribute */
697 static const char *jattrs[] = /* Requested job attributes */
699 "job-id",
700 "job-k-octets",
701 "job-name",
702 "job-originating-user-name",
703 "job-priority",
704 "job-state",
705 "time-at-creation",
707 static const char *pattrs[] = /* Requested printer attributes */
709 "printer-state",
710 "printer-state-message"
713 *q = NULL;
715 /* HACK ALERT!!! The porblem with support the 'printer name'
716 option is that we key the tdb off the sharename. So we will
717 overload the lpq_command string to pass in the printername
718 (which is basically what we do for non-cups printers ... using
719 the lpq_command to get the queue listing). */
721 fstrcpy( printername, lpq_command );
723 DEBUG(5,("cups_queue_get(%s, %p, %p)\n", printername, q, status));
726 * Make sure we don't ask for passwords...
729 cupsSetPasswordCB(cups_passwd_cb);
732 * Try to connect to the server...
735 if ((http = httpConnect(cups_server(), ippPort())) == NULL) {
736 DEBUG(0,("Unable to connect to CUPS server %s - %s\n",
737 cups_server(), strerror(errno)));
738 goto out;
742 * Generate the printer URI...
745 slprintf(uri, sizeof(uri) - 1, "ipp://localhost/printers/%s", printername);
748 * Build an IPP_GET_JOBS request, which requires the following
749 * attributes:
751 * attributes-charset
752 * attributes-natural-language
753 * requested-attributes
754 * printer-uri
757 request = ippNew();
759 request->request.op.operation_id = IPP_GET_JOBS;
760 request->request.op.request_id = 1;
762 language = cupsLangDefault();
764 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
765 "attributes-charset", NULL, cupsLangEncoding(language));
767 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
768 "attributes-natural-language", NULL, language->language);
770 ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
771 "requested-attributes",
772 (sizeof(jattrs) / sizeof(jattrs[0])),
773 NULL, jattrs);
775 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
776 "printer-uri", NULL, uri);
779 * Do the request and get back a response...
782 if ((response = cupsDoRequest(http, request, "/")) == NULL) {
783 DEBUG(0,("Unable to get jobs for %s - %s\n", uri,
784 ippErrorString(cupsLastError())));
785 goto out;
788 if (response->request.status.status_code >= IPP_OK_CONFLICT) {
789 DEBUG(0,("Unable to get jobs for %s - %s\n", uri,
790 ippErrorString(response->request.status.status_code)));
791 goto out;
795 * Process the jobs...
798 qcount = 0;
799 qalloc = 0;
800 queue = NULL;
802 for (attr = response->attrs; attr != NULL; attr = attr->next) {
804 * Skip leading attributes until we hit a job...
807 while (attr != NULL && attr->group_tag != IPP_TAG_JOB)
808 attr = attr->next;
810 if (attr == NULL)
811 break;
814 * Allocate memory as needed...
816 if (qcount >= qalloc) {
817 qalloc += 16;
819 temp = SMB_REALLOC_ARRAY(queue, print_queue_struct, qalloc);
821 if (temp == NULL) {
822 DEBUG(0,("cups_queue_get: Not enough memory!"));
823 qcount = 0;
824 SAFE_FREE(queue);
825 goto out;
828 queue = temp;
831 temp = queue + qcount;
832 memset(temp, 0, sizeof(print_queue_struct));
835 * Pull the needed attributes from this job...
838 job_id = 0;
839 job_priority = 50;
840 job_status = IPP_JOB_PENDING;
841 job_time = 0;
842 job_k_octets = 0;
843 user_name = NULL;
844 job_name = NULL;
846 while (attr != NULL && attr->group_tag == IPP_TAG_JOB) {
847 if (attr->name == NULL) {
848 attr = attr->next;
849 break;
852 if (strcmp(attr->name, "job-id") == 0 &&
853 attr->value_tag == IPP_TAG_INTEGER)
854 job_id = attr->values[0].integer;
856 if (strcmp(attr->name, "job-k-octets") == 0 &&
857 attr->value_tag == IPP_TAG_INTEGER)
858 job_k_octets = attr->values[0].integer;
860 if (strcmp(attr->name, "job-priority") == 0 &&
861 attr->value_tag == IPP_TAG_INTEGER)
862 job_priority = attr->values[0].integer;
864 if (strcmp(attr->name, "job-state") == 0 &&
865 attr->value_tag == IPP_TAG_ENUM)
866 job_status = (ipp_jstate_t)(attr->values[0].integer);
868 if (strcmp(attr->name, "time-at-creation") == 0 &&
869 attr->value_tag == IPP_TAG_INTEGER)
870 job_time = attr->values[0].integer;
872 if (strcmp(attr->name, "job-name") == 0 &&
873 attr->value_tag == IPP_TAG_NAME)
874 job_name = attr->values[0].string.text;
876 if (strcmp(attr->name, "job-originating-user-name") == 0 &&
877 attr->value_tag == IPP_TAG_NAME)
878 user_name = attr->values[0].string.text;
880 attr = attr->next;
884 * See if we have everything needed...
887 if (user_name == NULL || job_name == NULL || job_id == 0) {
888 if (attr == NULL)
889 break;
890 else
891 continue;
894 temp->job = job_id;
895 temp->size = job_k_octets * 1024;
896 temp->status = job_status == IPP_JOB_PENDING ? LPQ_QUEUED :
897 job_status == IPP_JOB_STOPPED ? LPQ_PAUSED :
898 job_status == IPP_JOB_HELD ? LPQ_PAUSED :
899 LPQ_PRINTING;
900 temp->priority = job_priority;
901 temp->time = job_time;
902 strncpy(temp->fs_user, user_name, sizeof(temp->fs_user) - 1);
903 strncpy(temp->fs_file, job_name, sizeof(temp->fs_file) - 1);
905 qcount ++;
907 if (attr == NULL)
908 break;
911 ippDelete(response);
912 response = NULL;
915 * Build an IPP_GET_PRINTER_ATTRIBUTES request, which requires the
916 * following attributes:
918 * attributes-charset
919 * attributes-natural-language
920 * requested-attributes
921 * printer-uri
924 request = ippNew();
926 request->request.op.operation_id = IPP_GET_PRINTER_ATTRIBUTES;
927 request->request.op.request_id = 1;
929 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
930 "attributes-charset", NULL, cupsLangEncoding(language));
932 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
933 "attributes-natural-language", NULL, language->language);
935 ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
936 "requested-attributes",
937 (sizeof(pattrs) / sizeof(pattrs[0])),
938 NULL, pattrs);
940 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
941 "printer-uri", NULL, uri);
944 * Do the request and get back a response...
947 if ((response = cupsDoRequest(http, request, "/")) == NULL) {
948 DEBUG(0,("Unable to get printer status for %s - %s\n", printername,
949 ippErrorString(cupsLastError())));
950 *q = queue;
951 goto out;
954 if (response->request.status.status_code >= IPP_OK_CONFLICT) {
955 DEBUG(0,("Unable to get printer status for %s - %s\n", printername,
956 ippErrorString(response->request.status.status_code)));
957 *q = queue;
958 goto out;
962 * Get the current printer status and convert it to the SAMBA values.
965 if ((attr = ippFindAttribute(response, "printer-state", IPP_TAG_ENUM)) != NULL) {
966 if (attr->values[0].integer == IPP_PRINTER_STOPPED)
967 status->status = LPSTAT_STOPPED;
968 else
969 status->status = LPSTAT_OK;
972 if ((attr = ippFindAttribute(response, "printer-state-message",
973 IPP_TAG_TEXT)) != NULL)
974 fstrcpy(status->message, attr->values[0].string.text);
977 * Return the job queue...
980 *q = queue;
982 out:
983 if (response)
984 ippDelete(response);
986 if (language)
987 cupsLangFree(language);
989 if (http)
990 httpClose(http);
992 return qcount;
997 * 'cups_queue_pause()' - Pause a print queue.
1000 static int cups_queue_pause(int snum)
1002 extern userdom_struct current_user_info;
1003 int ret = 1; /* Return value */
1004 http_t *http = NULL; /* HTTP connection to server */
1005 ipp_t *request = NULL, /* IPP Request */
1006 *response = NULL; /* IPP Response */
1007 cups_lang_t *language = NULL; /* Default language */
1008 char uri[HTTP_MAX_URI]; /* printer-uri attribute */
1011 DEBUG(5,("cups_queue_pause(%d)\n", snum));
1014 * Make sure we don't ask for passwords...
1017 cupsSetPasswordCB(cups_passwd_cb);
1020 * Try to connect to the server...
1023 if ((http = httpConnect(cups_server(), ippPort())) == NULL) {
1024 DEBUG(0,("Unable to connect to CUPS server %s - %s\n",
1025 cups_server(), strerror(errno)));
1026 goto out;
1030 * Build an IPP_PAUSE_PRINTER request, which requires the following
1031 * attributes:
1033 * attributes-charset
1034 * attributes-natural-language
1035 * printer-uri
1036 * requesting-user-name
1039 request = ippNew();
1041 request->request.op.operation_id = IPP_PAUSE_PRINTER;
1042 request->request.op.request_id = 1;
1044 language = cupsLangDefault();
1046 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
1047 "attributes-charset", NULL, cupsLangEncoding(language));
1049 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
1050 "attributes-natural-language", NULL, language->language);
1052 slprintf(uri, sizeof(uri) - 1, "ipp://localhost/printers/%s",
1053 PRINTERNAME(snum));
1055 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, uri);
1057 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
1058 NULL, current_user_info.unix_name);
1061 * Do the request and get back a response...
1064 if ((response = cupsDoRequest(http, request, "/admin/")) != NULL) {
1065 if (response->request.status.status_code >= IPP_OK_CONFLICT) {
1066 DEBUG(0,("Unable to pause printer %s - %s\n", PRINTERNAME(snum),
1067 ippErrorString(cupsLastError())));
1068 } else {
1069 ret = 0;
1071 } else {
1072 DEBUG(0,("Unable to pause printer %s - %s\n", PRINTERNAME(snum),
1073 ippErrorString(cupsLastError())));
1076 out:
1077 if (response)
1078 ippDelete(response);
1080 if (language)
1081 cupsLangFree(language);
1083 if (http)
1084 httpClose(http);
1086 return ret;
1091 * 'cups_queue_resume()' - Restart a print queue.
1094 static int cups_queue_resume(int snum)
1096 extern userdom_struct current_user_info;
1097 int ret = 1; /* Return value */
1098 http_t *http = NULL; /* HTTP connection to server */
1099 ipp_t *request = NULL, /* IPP Request */
1100 *response = NULL; /* IPP Response */
1101 cups_lang_t *language = NULL; /* Default language */
1102 char uri[HTTP_MAX_URI]; /* printer-uri attribute */
1105 DEBUG(5,("cups_queue_resume(%d)\n", snum));
1108 * Make sure we don't ask for passwords...
1111 cupsSetPasswordCB(cups_passwd_cb);
1114 * Try to connect to the server...
1117 if ((http = httpConnect(cups_server(), ippPort())) == NULL) {
1118 DEBUG(0,("Unable to connect to CUPS server %s - %s\n",
1119 cups_server(), strerror(errno)));
1120 goto out;
1124 * Build an IPP_RESUME_PRINTER request, which requires the following
1125 * attributes:
1127 * attributes-charset
1128 * attributes-natural-language
1129 * printer-uri
1130 * requesting-user-name
1133 request = ippNew();
1135 request->request.op.operation_id = IPP_RESUME_PRINTER;
1136 request->request.op.request_id = 1;
1138 language = cupsLangDefault();
1140 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
1141 "attributes-charset", NULL, cupsLangEncoding(language));
1143 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
1144 "attributes-natural-language", NULL, language->language);
1146 slprintf(uri, sizeof(uri) - 1, "ipp://localhost/printers/%s",
1147 PRINTERNAME(snum));
1149 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, uri);
1151 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
1152 NULL, current_user_info.unix_name);
1155 * Do the request and get back a response...
1158 if ((response = cupsDoRequest(http, request, "/admin/")) != NULL) {
1159 if (response->request.status.status_code >= IPP_OK_CONFLICT) {
1160 DEBUG(0,("Unable to resume printer %s - %s\n", PRINTERNAME(snum),
1161 ippErrorString(cupsLastError())));
1162 } else {
1163 ret = 0;
1165 } else {
1166 DEBUG(0,("Unable to resume printer %s - %s\n", PRINTERNAME(snum),
1167 ippErrorString(cupsLastError())));
1170 out:
1171 if (response)
1172 ippDelete(response);
1174 if (language)
1175 cupsLangFree(language);
1177 if (http)
1178 httpClose(http);
1180 return ret;
1183 /*******************************************************************
1184 * CUPS printing interface definitions...
1185 ******************************************************************/
1187 struct printif cups_printif =
1189 PRINT_CUPS,
1190 cups_queue_get,
1191 cups_queue_pause,
1192 cups_queue_resume,
1193 cups_job_delete,
1194 cups_job_pause,
1195 cups_job_resume,
1196 cups_job_submit,
1199 #else
1200 /* this keeps fussy compilers happy */
1201 void print_cups_dummy(void) {}
1202 #endif /* HAVE_CUPS */