Make sure we don't clobber the stack when response consists of the empty
[Samba/gebeck_regimport.git] / source3 / printing / print_cups.c
blobf0096a17c2c40a42c082eb0288ac2039716b8e9f
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 printing interface definitions...
33 static int cups_job_delete(int snum, struct printjob *pjob);
34 static int cups_job_pause(int snum, struct printjob *pjob);
35 static int cups_job_resume(int snum, struct printjob *pjob);
36 static int cups_job_submit(int snum, struct printjob *pjob);
37 static int cups_queue_get(int snum, print_queue_struct **q,
38 print_status_struct *status);
39 static int cups_queue_pause(int snum);
40 static int cups_queue_resume(int snum);
43 struct printif cups_printif =
45 cups_queue_get,
46 cups_queue_pause,
47 cups_queue_resume,
48 cups_job_delete,
49 cups_job_pause,
50 cups_job_resume,
51 cups_job_submit,
55 * 'cups_passwd_cb()' - The CUPS password callback...
58 static const char * /* O - Password or NULL */
59 cups_passwd_cb(const char *prompt) /* I - Prompt */
62 * Always return NULL to indicate that no password is available...
65 return (NULL);
70 * 'cups_printer_fn()' - Call a function for every printer known to the
71 * system.
74 void cups_printer_fn(void (*fn)(char *, char *))
76 /* I - Function to call */
77 http_t *http; /* HTTP connection to server */
78 ipp_t *request, /* IPP Request */
79 *response; /* IPP Response */
80 ipp_attribute_t *attr; /* Current attribute */
81 cups_lang_t *language; /* Default language */
82 char *name, /* printer-name attribute */
83 *make_model, /* printer-make-and-model attribute */
84 *info; /* printer-info attribute */
85 static const char *requested[] =/* Requested attributes */
87 "printer-name",
88 "printer-make-and-model",
89 "printer-info"
90 };
93 DEBUG(5,("cups_printer_fn(%p)\n", fn));
96 * Make sure we don't ask for passwords...
99 cupsSetPasswordCB(cups_passwd_cb);
102 * Try to connect to the server...
105 if ((http = httpConnect(cupsServer(), ippPort())) == NULL)
107 DEBUG(0,("Unable to connect to CUPS server %s - %s\n",
108 cupsServer(), strerror(errno)));
109 return;
113 * Build a CUPS_GET_PRINTERS request, which requires the following
114 * attributes:
116 * attributes-charset
117 * attributes-natural-language
118 * requested-attributes
121 request = ippNew();
123 request->request.op.operation_id = CUPS_GET_PRINTERS;
124 request->request.op.request_id = 1;
126 language = cupsLangDefault();
128 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
129 "attributes-charset", NULL, cupsLangEncoding(language));
131 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
132 "attributes-natural-language", NULL, language->language);
134 ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
135 "requested-attributes",
136 (sizeof(requested) / sizeof(requested[0])),
137 NULL, requested);
140 * Do the request and get back a response...
143 if ((response = cupsDoRequest(http, request, "/")) == NULL)
145 DEBUG(0,("Unable to get printer list - %s\n",
146 ippErrorString(cupsLastError())));
147 httpClose(http);
148 return;
151 for (attr = response->attrs; attr != NULL;)
154 * Skip leading attributes until we hit a printer...
157 while (attr != NULL && attr->group_tag != IPP_TAG_PRINTER)
158 attr = attr->next;
160 if (attr == NULL)
161 break;
164 * Pull the needed attributes from this printer...
167 name = NULL;
168 make_model = NULL;
169 info = NULL;
171 while (attr != NULL && attr->group_tag == IPP_TAG_PRINTER)
173 if (strcmp(attr->name, "printer-name") == 0 &&
174 attr->value_tag == IPP_TAG_NAME)
175 name = attr->values[0].string.text;
177 if (strcmp(attr->name, "printer-make-and-model") == 0 &&
178 attr->value_tag == IPP_TAG_TEXT)
179 make_model = attr->values[0].string.text;
181 if (strcmp(attr->name, "printer-info") == 0 &&
182 attr->value_tag == IPP_TAG_TEXT)
183 info = attr->values[0].string.text;
185 attr = attr->next;
189 * See if we have everything needed...
192 if (name == NULL)
193 break;
195 if (info == NULL || !info[0])
196 (*fn)(name, make_model);
197 else
198 (*fn)(name, info);
203 ippDelete(response);
207 * Build a CUPS_GET_CLASSES request, which requires the following
208 * attributes:
210 * attributes-charset
211 * attributes-natural-language
212 * requested-attributes
215 request = ippNew();
217 request->request.op.operation_id = CUPS_GET_CLASSES;
218 request->request.op.request_id = 1;
220 language = cupsLangDefault();
222 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
223 "attributes-charset", NULL, cupsLangEncoding(language));
225 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
226 "attributes-natural-language", NULL, language->language);
228 ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
229 "requested-attributes",
230 (sizeof(requested) / sizeof(requested[0])),
231 NULL, requested);
234 * Do the request and get back a response...
237 if ((response = cupsDoRequest(http, request, "/")) == NULL)
239 DEBUG(0,("Unable to get printer list - %s\n",
240 ippErrorString(cupsLastError())));
241 httpClose(http);
242 return;
245 for (attr = response->attrs; attr != NULL;)
248 * Skip leading attributes until we hit a printer...
251 while (attr != NULL && attr->group_tag != IPP_TAG_PRINTER)
252 attr = attr->next;
254 if (attr == NULL)
255 break;
258 * Pull the needed attributes from this printer...
261 name = NULL;
262 make_model = NULL;
263 info = NULL;
265 while (attr != NULL && attr->group_tag == IPP_TAG_PRINTER)
267 if (strcmp(attr->name, "printer-name") == 0 &&
268 attr->value_tag == IPP_TAG_NAME)
269 name = attr->values[0].string.text;
271 if (strcmp(attr->name, "printer-make-and-model") == 0 &&
272 attr->value_tag == IPP_TAG_TEXT)
273 make_model = attr->values[0].string.text;
275 if (strcmp(attr->name, "printer-info") == 0 &&
276 attr->value_tag == IPP_TAG_TEXT)
277 info = attr->values[0].string.text;
279 attr = attr->next;
283 * See if we have everything needed...
286 if (name == NULL)
287 break;
289 if (info == NULL || !info[0])
290 (*fn)(name, make_model);
291 else
292 (*fn)(name, info);
297 ippDelete(response);
300 * Close the connection to the server...
303 httpClose(http);
308 * 'cups_printername_ok()' - Provide the equivalent of pcap_printername_ok()
309 * for CUPS.
310 * O - 1 if printer name OK
311 * I - Name of printer
313 int cups_printername_ok(const char *name)
315 http_t *http; /* HTTP connection to server */
316 ipp_t *request, /* IPP Request */
317 *response; /* IPP Response */
318 cups_lang_t *language; /* Default language */
319 char uri[HTTP_MAX_URI]; /* printer-uri attribute */
322 DEBUG(5,("cups_printername_ok(\"%s\")\n", name));
325 * Make sure we don't ask for passwords...
328 cupsSetPasswordCB(cups_passwd_cb);
331 * Try to connect to the server...
334 if ((http = httpConnect(cupsServer(), ippPort())) == NULL)
336 DEBUG(3,("Unable to connect to CUPS server %s - %s\n",
337 cupsServer(), strerror(errno)));
338 return (0);
342 * Build an IPP_GET_PRINTER_ATTRS request, which requires the following
343 * attributes:
345 * attributes-charset
346 * attributes-natural-language
347 * requested-attributes
348 * printer-uri
351 request = ippNew();
353 request->request.op.operation_id = IPP_GET_PRINTER_ATTRIBUTES;
354 request->request.op.request_id = 1;
356 language = cupsLangDefault();
358 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
359 "attributes-charset", NULL, cupsLangEncoding(language));
361 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
362 "attributes-natural-language", NULL, language->language);
364 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
365 "requested-attributes", NULL, "printer-uri");
367 slprintf(uri, sizeof(uri) - 1, "ipp://localhost/printers/%s", name);
369 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
370 "printer-uri", NULL, uri);
373 * Do the request and get back a response...
376 if ((response = cupsDoRequest(http, request, "/")) == NULL)
378 DEBUG(3,("Unable to get printer status for %s - %s\n", name,
379 ippErrorString(cupsLastError())));
380 httpClose(http);
381 return (0);
384 httpClose(http);
386 if (response->request.status.status_code >= IPP_OK_CONFLICT)
388 DEBUG(3,("Unable to get printer status for %s - %s\n", name,
389 ippErrorString(response->request.status.status_code)));
390 ippDelete(response);
391 return (0);
393 else
395 ippDelete(response);
396 return (1);
402 * 'cups_job_delete()' - Delete a job.
405 static int
406 cups_job_delete(int snum, struct printjob *pjob)
408 int ret; /* Return value */
409 http_t *http; /* HTTP connection to server */
410 ipp_t *request, /* IPP Request */
411 *response; /* IPP Response */
412 cups_lang_t *language; /* Default language */
413 char uri[HTTP_MAX_URI]; /* printer-uri attribute */
416 DEBUG(5,("cups_job_delete(%d, %p (%d))\n", snum, pjob, pjob->sysjob));
419 * Make sure we don't ask for passwords...
422 cupsSetPasswordCB(cups_passwd_cb);
425 * Try to connect to the server...
428 if ((http = httpConnect(cupsServer(), ippPort())) == NULL)
430 DEBUG(0,("Unable to connect to CUPS server %s - %s\n",
431 cupsServer(), strerror(errno)));
432 return (1);
436 * Build an IPP_CANCEL_JOB request, which requires the following
437 * attributes:
439 * attributes-charset
440 * attributes-natural-language
441 * job-uri
442 * requesting-user-name
445 request = ippNew();
447 request->request.op.operation_id = IPP_CANCEL_JOB;
448 request->request.op.request_id = 1;
450 language = cupsLangDefault();
452 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
453 "attributes-charset", NULL, cupsLangEncoding(language));
455 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
456 "attributes-natural-language", NULL, language->language);
458 slprintf(uri, sizeof(uri) - 1, "ipp://localhost/jobs/%d", pjob->sysjob);
460 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri", NULL, uri);
462 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
463 NULL, pjob->user);
466 * Do the request and get back a response...
469 ret = 1;
471 if ((response = cupsDoRequest(http, request, "/jobs")) != NULL)
473 if (response->request.status.status_code >= IPP_OK_CONFLICT)
474 DEBUG(0,("Unable to cancel job %d - %s\n", pjob->sysjob,
475 ippErrorString(cupsLastError())));
476 else
477 ret = 0;
479 ippDelete(response);
481 else
482 DEBUG(0,("Unable to cancel job %d - %s\n", pjob->sysjob,
483 ippErrorString(cupsLastError())));
485 httpClose(http);
487 return (ret);
492 * 'cups_job_pause()' - Pause a job.
495 static int
496 cups_job_pause(int snum, struct printjob *pjob)
498 int ret; /* Return value */
499 http_t *http; /* HTTP connection to server */
500 ipp_t *request, /* IPP Request */
501 *response; /* IPP Response */
502 cups_lang_t *language; /* Default language */
503 char uri[HTTP_MAX_URI]; /* printer-uri attribute */
506 DEBUG(5,("cups_job_pause(%d, %p (%d))\n", snum, pjob, pjob->sysjob));
509 * Make sure we don't ask for passwords...
512 cupsSetPasswordCB(cups_passwd_cb);
515 * Try to connect to the server...
518 if ((http = httpConnect(cupsServer(), ippPort())) == NULL)
520 DEBUG(0,("Unable to connect to CUPS server %s - %s\n",
521 cupsServer(), strerror(errno)));
522 return (1);
526 * Build an IPP_HOLD_JOB request, which requires the following
527 * attributes:
529 * attributes-charset
530 * attributes-natural-language
531 * job-uri
532 * requesting-user-name
535 request = ippNew();
537 request->request.op.operation_id = IPP_HOLD_JOB;
538 request->request.op.request_id = 1;
540 language = cupsLangDefault();
542 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
543 "attributes-charset", NULL, cupsLangEncoding(language));
545 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
546 "attributes-natural-language", NULL, language->language);
548 slprintf(uri, sizeof(uri) - 1, "ipp://localhost/jobs/%d", pjob->sysjob);
550 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri", NULL, uri);
552 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
553 NULL, pjob->user);
556 * Do the request and get back a response...
559 ret = 1;
561 if ((response = cupsDoRequest(http, request, "/jobs")) != NULL)
563 if (response->request.status.status_code >= IPP_OK_CONFLICT)
564 DEBUG(0,("Unable to hold job %d - %s\n", pjob->sysjob,
565 ippErrorString(cupsLastError())));
566 else
567 ret = 0;
569 ippDelete(response);
571 else
572 DEBUG(0,("Unable to hold job %d - %s\n", pjob->sysjob,
573 ippErrorString(cupsLastError())));
575 httpClose(http);
577 return (ret);
582 * 'cups_job_resume()' - Resume a paused job.
585 static int
586 cups_job_resume(int snum, struct printjob *pjob)
588 int ret; /* Return value */
589 http_t *http; /* HTTP connection to server */
590 ipp_t *request, /* IPP Request */
591 *response; /* IPP Response */
592 cups_lang_t *language; /* Default language */
593 char uri[HTTP_MAX_URI]; /* printer-uri attribute */
596 DEBUG(5,("cups_job_resume(%d, %p (%d))\n", snum, pjob, pjob->sysjob));
599 * Make sure we don't ask for passwords...
602 cupsSetPasswordCB(cups_passwd_cb);
605 * Try to connect to the server...
608 if ((http = httpConnect(cupsServer(), ippPort())) == NULL)
610 DEBUG(0,("Unable to connect to CUPS server %s - %s\n",
611 cupsServer(), strerror(errno)));
612 return (1);
616 * Build an IPP_RELEASE_JOB request, which requires the following
617 * attributes:
619 * attributes-charset
620 * attributes-natural-language
621 * job-uri
622 * requesting-user-name
625 request = ippNew();
627 request->request.op.operation_id = IPP_RELEASE_JOB;
628 request->request.op.request_id = 1;
630 language = cupsLangDefault();
632 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
633 "attributes-charset", NULL, cupsLangEncoding(language));
635 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
636 "attributes-natural-language", NULL, language->language);
638 slprintf(uri, sizeof(uri) - 1, "ipp://localhost/jobs/%d", pjob->sysjob);
640 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri", NULL, uri);
642 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
643 NULL, pjob->user);
646 * Do the request and get back a response...
649 ret = 1;
651 if ((response = cupsDoRequest(http, request, "/jobs")) != NULL)
653 if (response->request.status.status_code >= IPP_OK_CONFLICT)
654 DEBUG(0,("Unable to release job %d - %s\n", pjob->sysjob,
655 ippErrorString(cupsLastError())));
656 else
657 ret = 0;
659 ippDelete(response);
661 else
662 DEBUG(0,("Unable to release job %d - %s\n", pjob->sysjob,
663 ippErrorString(cupsLastError())));
665 httpClose(http);
667 return (ret);
672 * 'cups_job_submit()' - Submit a job for printing.
675 static int
676 cups_job_submit(int snum, struct printjob *pjob)
678 int ret; /* Return value */
679 http_t *http; /* HTTP connection to server */
680 ipp_t *request, /* IPP Request */
681 *response; /* IPP Response */
682 cups_lang_t *language; /* Default language */
683 char uri[HTTP_MAX_URI]; /* printer-uri attribute */
684 char *clientname; /* hostname of client for job-originating-host attribute */
685 pstring new_jobname;
687 DEBUG(5,("cups_job_submit(%d, %p (%d))\n", snum, pjob, pjob->sysjob));
690 * Make sure we don't ask for passwords...
693 cupsSetPasswordCB(cups_passwd_cb);
696 * Try to connect to the server...
699 if ((http = httpConnect(cupsServer(), ippPort())) == NULL)
701 DEBUG(0,("Unable to connect to CUPS server %s - %s\n",
702 cupsServer(), strerror(errno)));
703 return (1);
707 * Build an IPP_PRINT_JOB request, which requires the following
708 * attributes:
710 * attributes-charset
711 * attributes-natural-language
712 * printer-uri
713 * requesting-user-name
714 * [document-data]
717 request = ippNew();
719 request->request.op.operation_id = IPP_PRINT_JOB;
720 request->request.op.request_id = 1;
722 language = cupsLangDefault();
724 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
725 "attributes-charset", NULL, cupsLangEncoding(language));
727 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
728 "attributes-natural-language", NULL, language->language);
730 slprintf(uri, sizeof(uri) - 1, "ipp://localhost/printers/%s",
731 PRINTERNAME(snum));
733 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
734 "printer-uri", NULL, uri);
736 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
737 NULL, pjob->user);
739 clientname = client_name();
740 if (strcmp(clientname, "UNKNOWN") == 0) {
741 clientname = client_addr();
744 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
745 "job-originating-host-name", NULL,
746 clientname);
748 pstr_sprintf(new_jobname,"%s%.8u %s", PRINT_SPOOL_PREFIX,
749 (unsigned int)pjob->smbjob, pjob->jobname);
751 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "job-name", NULL,
752 new_jobname);
755 * Do the request and get back a response...
758 slprintf(uri, sizeof(uri) - 1, "/printers/%s", PRINTERNAME(snum));
760 ret = 1;
761 if ((response = cupsDoFileRequest(http, request, uri,
762 pjob->filename)) != NULL)
764 if (response->request.status.status_code >= IPP_OK_CONFLICT)
765 DEBUG(0,("Unable to print file to %s - %s\n", PRINTERNAME(snum),
766 ippErrorString(cupsLastError())));
767 else
768 ret = 0;
770 ippDelete(response);
772 else
773 DEBUG(0,("Unable to print file to `%s' - %s\n", PRINTERNAME(snum),
774 ippErrorString(cupsLastError())));
776 httpClose(http);
778 if ( ret == 0 )
779 unlink(pjob->filename);
780 /* else print_job_end will do it for us */
782 return (ret);
787 * 'cups_queue_get()' - Get all the jobs in the print queue.
790 static int
791 cups_queue_get(int snum, print_queue_struct **q, print_status_struct *status)
793 http_t *http; /* HTTP connection to server */
794 ipp_t *request, /* IPP Request */
795 *response; /* IPP Response */
796 ipp_attribute_t *attr; /* Current attribute */
797 cups_lang_t *language; /* Default language */
798 char uri[HTTP_MAX_URI]; /* printer-uri attribute */
799 int qcount, /* Number of active queue entries */
800 qalloc; /* Number of queue entries allocated */
801 print_queue_struct *queue, /* Queue entries */
802 *temp; /* Temporary pointer for queue */
803 const char *user_name, /* job-originating-user-name attribute */
804 *job_name; /* job-name attribute */
805 int job_id; /* job-id attribute */
806 int job_k_octets; /* job-k-octets attribute */
807 time_t job_time; /* time-at-creation attribute */
808 ipp_jstate_t job_status; /* job-status attribute */
809 int job_priority; /* job-priority attribute */
810 static const char *jattrs[] = /* Requested job attributes */
812 "job-id",
813 "job-k-octets",
814 "job-name",
815 "job-originating-user-name",
816 "job-priority",
817 "job-state",
818 "time-at-creation",
820 static const char *pattrs[] = /* Requested printer attributes */
822 "printer-state",
823 "printer-state-message"
827 DEBUG(5,("cups_queue_get(%d, %p, %p)\n", snum, q, status));
830 * Make sure we don't ask for passwords...
833 cupsSetPasswordCB(cups_passwd_cb);
836 * Try to connect to the server...
839 if ((http = httpConnect(cupsServer(), ippPort())) == NULL)
841 DEBUG(0,("Unable to connect to CUPS server %s - %s\n",
842 cupsServer(), strerror(errno)));
843 return (0);
847 * Generate the printer URI...
850 slprintf(uri, sizeof(uri) - 1, "ipp://localhost/printers/%s",
851 PRINTERNAME(snum));
854 * Build an IPP_GET_JOBS request, which requires the following
855 * attributes:
857 * attributes-charset
858 * attributes-natural-language
859 * requested-attributes
860 * printer-uri
863 request = ippNew();
865 request->request.op.operation_id = IPP_GET_JOBS;
866 request->request.op.request_id = 1;
868 language = cupsLangDefault();
870 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
871 "attributes-charset", NULL, cupsLangEncoding(language));
873 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
874 "attributes-natural-language", NULL, language->language);
876 ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
877 "requested-attributes",
878 (sizeof(jattrs) / sizeof(jattrs[0])),
879 NULL, jattrs);
881 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
882 "printer-uri", NULL, uri);
885 * Do the request and get back a response...
888 if ((response = cupsDoRequest(http, request, "/")) == NULL)
890 DEBUG(0,("Unable to get jobs for %s - %s\n", uri,
891 ippErrorString(cupsLastError())));
892 httpClose(http);
893 return (0);
896 if (response->request.status.status_code >= IPP_OK_CONFLICT)
898 DEBUG(0,("Unable to get jobs for %s - %s\n", uri,
899 ippErrorString(response->request.status.status_code)));
900 ippDelete(response);
901 httpClose(http);
903 return (0);
907 * Process the jobs...
910 qcount = 0;
911 qalloc = 0;
912 queue = NULL;
914 for (attr = response->attrs; attr != NULL; attr = attr->next)
917 * Skip leading attributes until we hit a job...
920 while (attr != NULL && attr->group_tag != IPP_TAG_JOB)
921 attr = attr->next;
923 if (attr == NULL)
924 break;
927 * Allocate memory as needed...
929 if (qcount >= qalloc)
931 qalloc += 16;
933 temp = Realloc(queue, sizeof(print_queue_struct) * qalloc);
935 if (temp == NULL)
937 DEBUG(0,("cups_queue_get: Not enough memory!"));
938 ippDelete(response);
939 httpClose(http);
941 SAFE_FREE(queue);
942 return (0);
945 queue = temp;
948 temp = queue + qcount;
949 memset(temp, 0, sizeof(print_queue_struct));
952 * Pull the needed attributes from this job...
955 job_id = 0;
956 job_priority = 50;
957 job_status = IPP_JOB_PENDING;
958 job_time = 0;
959 job_k_octets = 0;
960 user_name = NULL;
961 job_name = NULL;
963 while (attr != NULL && attr->group_tag == IPP_TAG_JOB)
965 if (attr->name == NULL)
967 attr = attr->next;
968 break;
971 if (strcmp(attr->name, "job-id") == 0 &&
972 attr->value_tag == IPP_TAG_INTEGER)
973 job_id = attr->values[0].integer;
975 if (strcmp(attr->name, "job-k-octets") == 0 &&
976 attr->value_tag == IPP_TAG_INTEGER)
977 job_k_octets = attr->values[0].integer;
979 if (strcmp(attr->name, "job-priority") == 0 &&
980 attr->value_tag == IPP_TAG_INTEGER)
981 job_priority = attr->values[0].integer;
983 if (strcmp(attr->name, "job-state") == 0 &&
984 attr->value_tag == IPP_TAG_ENUM)
985 job_status = (ipp_jstate_t)(attr->values[0].integer);
987 if (strcmp(attr->name, "time-at-creation") == 0 &&
988 attr->value_tag == IPP_TAG_INTEGER)
989 job_time = attr->values[0].integer;
991 if (strcmp(attr->name, "job-name") == 0 &&
992 attr->value_tag == IPP_TAG_NAME)
993 job_name = attr->values[0].string.text;
995 if (strcmp(attr->name, "job-originating-user-name") == 0 &&
996 attr->value_tag == IPP_TAG_NAME)
997 user_name = attr->values[0].string.text;
999 attr = attr->next;
1003 * See if we have everything needed...
1006 if (user_name == NULL || job_name == NULL || job_id == 0)
1008 if (attr == NULL)
1009 break;
1010 else
1011 continue;
1014 temp->job = job_id;
1015 temp->size = job_k_octets * 1024;
1016 temp->status = job_status == IPP_JOB_PENDING ? LPQ_QUEUED :
1017 job_status == IPP_JOB_STOPPED ? LPQ_PAUSED :
1018 job_status == IPP_JOB_HELD ? LPQ_PAUSED :
1019 LPQ_PRINTING;
1020 temp->priority = job_priority;
1021 temp->time = job_time;
1022 strncpy(temp->fs_user, user_name, sizeof(temp->fs_user) - 1);
1023 strncpy(temp->fs_file, job_name, sizeof(temp->fs_file) - 1);
1025 qcount ++;
1027 if (attr == NULL)
1028 break;
1031 ippDelete(response);
1034 * Build an IPP_GET_PRINTER_ATTRIBUTES request, which requires the
1035 * following attributes:
1037 * attributes-charset
1038 * attributes-natural-language
1039 * requested-attributes
1040 * printer-uri
1043 request = ippNew();
1045 request->request.op.operation_id = IPP_GET_PRINTER_ATTRIBUTES;
1046 request->request.op.request_id = 1;
1048 language = cupsLangDefault();
1050 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
1051 "attributes-charset", NULL, cupsLangEncoding(language));
1053 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
1054 "attributes-natural-language", NULL, language->language);
1056 ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
1057 "requested-attributes",
1058 (sizeof(pattrs) / sizeof(pattrs[0])),
1059 NULL, pattrs);
1061 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
1062 "printer-uri", NULL, uri);
1065 * Do the request and get back a response...
1068 if ((response = cupsDoRequest(http, request, "/")) == NULL)
1070 DEBUG(0,("Unable to get printer status for %s - %s\n", PRINTERNAME(snum),
1071 ippErrorString(cupsLastError())));
1072 httpClose(http);
1073 *q = queue;
1074 return (qcount);
1077 if (response->request.status.status_code >= IPP_OK_CONFLICT)
1079 DEBUG(0,("Unable to get printer status for %s - %s\n", PRINTERNAME(snum),
1080 ippErrorString(response->request.status.status_code)));
1081 ippDelete(response);
1082 httpClose(http);
1083 *q = queue;
1084 return (qcount);
1088 * Get the current printer status and convert it to the SAMBA values.
1091 if ((attr = ippFindAttribute(response, "printer-state", IPP_TAG_ENUM)) != NULL)
1093 if (attr->values[0].integer == IPP_PRINTER_STOPPED)
1094 status->status = LPSTAT_STOPPED;
1095 else
1096 status->status = LPSTAT_OK;
1099 if ((attr = ippFindAttribute(response, "printer-state-message",
1100 IPP_TAG_TEXT)) != NULL)
1101 fstrcpy(status->message, attr->values[0].string.text);
1103 ippDelete(response);
1106 * Return the job queue...
1109 httpClose(http);
1111 *q = queue;
1112 return (qcount);
1117 * 'cups_queue_pause()' - Pause a print queue.
1120 static int
1121 cups_queue_pause(int snum)
1123 extern userdom_struct current_user_info;
1124 int ret; /* Return value */
1125 http_t *http; /* HTTP connection to server */
1126 ipp_t *request, /* IPP Request */
1127 *response; /* IPP Response */
1128 cups_lang_t *language; /* Default language */
1129 char uri[HTTP_MAX_URI]; /* printer-uri attribute */
1132 DEBUG(5,("cups_queue_pause(%d)\n", snum));
1135 * Make sure we don't ask for passwords...
1138 cupsSetPasswordCB(cups_passwd_cb);
1141 * Try to connect to the server...
1144 if ((http = httpConnect(cupsServer(), ippPort())) == NULL)
1146 DEBUG(0,("Unable to connect to CUPS server %s - %s\n",
1147 cupsServer(), strerror(errno)));
1148 return (1);
1152 * Build an IPP_PAUSE_PRINTER request, which requires the following
1153 * attributes:
1155 * attributes-charset
1156 * attributes-natural-language
1157 * printer-uri
1158 * requesting-user-name
1161 request = ippNew();
1163 request->request.op.operation_id = IPP_PAUSE_PRINTER;
1164 request->request.op.request_id = 1;
1166 language = cupsLangDefault();
1168 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
1169 "attributes-charset", NULL, cupsLangEncoding(language));
1171 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
1172 "attributes-natural-language", NULL, language->language);
1174 slprintf(uri, sizeof(uri) - 1, "ipp://localhost/printers/%s",
1175 PRINTERNAME(snum));
1177 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, uri);
1179 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
1180 NULL, current_user_info.unix_name);
1183 * Do the request and get back a response...
1186 ret = 1;
1188 if ((response = cupsDoRequest(http, request, "/admin/")) != NULL)
1190 if (response->request.status.status_code >= IPP_OK_CONFLICT)
1191 DEBUG(0,("Unable to pause printer %s - %s\n", PRINTERNAME(snum),
1192 ippErrorString(cupsLastError())));
1193 else
1194 ret = 0;
1196 ippDelete(response);
1198 else
1199 DEBUG(0,("Unable to pause printer %s - %s\n", PRINTERNAME(snum),
1200 ippErrorString(cupsLastError())));
1202 httpClose(http);
1204 return (ret);
1209 * 'cups_queue_resume()' - Restart a print queue.
1212 static int
1213 cups_queue_resume(int snum)
1215 extern userdom_struct current_user_info;
1216 int ret; /* Return value */
1217 http_t *http; /* HTTP connection to server */
1218 ipp_t *request, /* IPP Request */
1219 *response; /* IPP Response */
1220 cups_lang_t *language; /* Default language */
1221 char uri[HTTP_MAX_URI]; /* printer-uri attribute */
1224 DEBUG(5,("cups_queue_resume(%d)\n", snum));
1227 * Make sure we don't ask for passwords...
1230 cupsSetPasswordCB(cups_passwd_cb);
1233 * Try to connect to the server...
1236 if ((http = httpConnect(cupsServer(), ippPort())) == NULL)
1238 DEBUG(0,("Unable to connect to CUPS server %s - %s\n",
1239 cupsServer(), strerror(errno)));
1240 return (1);
1244 * Build an IPP_RESUME_PRINTER request, which requires the following
1245 * attributes:
1247 * attributes-charset
1248 * attributes-natural-language
1249 * printer-uri
1250 * requesting-user-name
1253 request = ippNew();
1255 request->request.op.operation_id = IPP_RESUME_PRINTER;
1256 request->request.op.request_id = 1;
1258 language = cupsLangDefault();
1260 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
1261 "attributes-charset", NULL, cupsLangEncoding(language));
1263 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
1264 "attributes-natural-language", NULL, language->language);
1266 slprintf(uri, sizeof(uri) - 1, "ipp://localhost/printers/%s",
1267 PRINTERNAME(snum));
1269 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, uri);
1271 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
1272 NULL, current_user_info.unix_name);
1275 * Do the request and get back a response...
1278 ret = 1;
1280 if ((response = cupsDoRequest(http, request, "/admin/")) != NULL)
1282 if (response->request.status.status_code >= IPP_OK_CONFLICT)
1283 DEBUG(0,("Unable to resume printer %s - %s\n", PRINTERNAME(snum),
1284 ippErrorString(cupsLastError())));
1285 else
1286 ret = 0;
1288 ippDelete(response);
1290 else
1291 DEBUG(0,("Unable to resume printer %s - %s\n", PRINTERNAME(snum),
1292 ippErrorString(cupsLastError())));
1294 httpClose(http);
1296 return (ret);
1300 #else
1301 /* this keeps fussy compilers happy */
1302 void print_cups_dummy(void) {}
1303 #endif /* HAVE_CUPS */