Removed 'extern int DEBUGLEVEL' as it is now in the smb.h header.
[nivanova/samba-autobuild/.git] / source3 / printing / print_cups.c
1 /*
2  * Support code for the Common UNIX Printing System ("CUPS")
3  *
4  * Copyright 1999-2001 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 "printing.h"
22 #include "smb.h"
23
24 #ifdef HAVE_CUPS
25 #include <cups/cups.h>
26 #include <cups/language.h>
27
28
29 /*
30  * CUPS printing interface definitions...
31  */
32
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);
41
42
43 struct printif  cups_printif =
44                 {
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,
52                 };
53
54 /*
55  * 'cups_passwd_cb()' - The CUPS password callback...
56  */
57
58 const char *                            /* O - Password or NULL */
59 cups_passwd_cb(const char *prompt)      /* I - Prompt */
60 {
61  /*
62   * Always return NULL to indicate that no password is available...
63   */
64
65   (void)prompt;
66
67   return (NULL);
68 }
69
70
71 /*
72  * 'cups_printer_fn()' - Call a function for every printer known to the
73  *                       system.
74  */
75
76 void
77 cups_printer_fn(void (*fn)(char *, char *))     /* I - Function to call */
78 {
79         http_t          *http;          /* HTTP connection to server */
80         ipp_t           *request,       /* IPP Request */
81                         *response;      /* IPP Response */
82         ipp_attribute_t *attr;          /* Current attribute */
83         cups_lang_t     *language;      /* Default language */
84         char            *name,          /* printer-name attribute */
85                         *make_model,    /* printer-make-and-model attribute */
86                         *info;          /* printer-info attribute */
87         static const char *requested[] =/* Requested attributes */
88                         {
89                           "printer-name",
90                           "printer-make-and-model",
91                           "printer-info"
92                         };       
93
94
95         DEBUG(5,("cups_printer_fn(%p)\n", fn));
96
97        /*
98         * Make sure we don't ask for passwords...
99         */
100
101         cupsSetPasswordCB(cups_passwd_cb);
102
103        /*
104         * Try to connect to the server...
105         */
106
107         if ((http = httpConnect(cupsServer(), ippPort())) == NULL)
108         {
109                 DEBUG(0,("Unable to connect to CUPS server %s - %s\n", 
110                          cupsServer(), strerror(errno)));
111                 return;
112         }
113
114        /*
115         * Build a CUPS_GET_PRINTERS request, which requires the following
116         * attributes:
117         *
118         *    attributes-charset
119         *    attributes-natural-language
120         *    requested-attributes
121         */
122
123         request = ippNew();
124
125         request->request.op.operation_id = CUPS_GET_PRINTERS;
126         request->request.op.request_id   = 1;
127
128         language = cupsLangDefault();
129
130         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
131                      "attributes-charset", NULL, cupsLangEncoding(language));
132
133         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
134                      "attributes-natural-language", NULL, language->language);
135
136         ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
137                       "requested-attributes",
138                       (sizeof(requested) / sizeof(requested[0])),
139                       NULL, requested);
140
141        /*
142         * Do the request and get back a response...
143         */
144
145         if ((response = cupsDoRequest(http, request, "/")) == NULL)
146         {
147                 DEBUG(0,("Unable to get printer list - %s\n",
148                          ippErrorString(cupsLastError())));
149                 httpClose(http);
150                 return;
151         }
152
153         for (attr = response->attrs; attr != NULL;)
154         {
155                /*
156                 * Skip leading attributes until we hit a printer...
157                 */
158
159                 while (attr != NULL && attr->group_tag != IPP_TAG_PRINTER)
160                         attr = attr->next;
161
162                 if (attr == NULL)
163                         break;
164
165                /*
166                 * Pull the needed attributes from this printer...
167                 */
168
169                 name       = NULL;
170                 make_model = NULL;
171                 info       = NULL;
172
173                 while (attr != NULL && attr->group_tag == IPP_TAG_PRINTER)
174                 {
175                         if (strcmp(attr->name, "printer-name") == 0 &&
176                             attr->value_tag == IPP_TAG_NAME)
177                                 name = attr->values[0].string.text;
178
179                         if (strcmp(attr->name, "printer-make-and-model") == 0 &&
180                             attr->value_tag == IPP_TAG_TEXT)
181                                 make_model = attr->values[0].string.text;
182
183                         if (strcmp(attr->name, "printer-info") == 0 &&
184                             attr->value_tag == IPP_TAG_TEXT)
185                                 info = attr->values[0].string.text;
186
187                         attr = attr->next;
188                 }
189
190                /*
191                 * See if we have everything needed...
192                 */
193
194                 if (name == NULL)
195                         break;
196
197                 if (info == NULL || !info[0])
198                         (*fn)(name, make_model);
199                 else
200                         (*fn)(name,info);
201                 
202
203         }
204
205         ippDelete(response);
206         httpClose(http);
207 }
208
209
210 /*
211  * 'cups_printername_ok()' - Provide the equivalent of pcap_printername_ok()
212  *                           for CUPS.
213  */
214
215 int                                     /* O - 1 if printer name OK */
216 cups_printername_ok(char *name)         /* I - Name of printer */
217 {
218         http_t          *http;          /* HTTP connection to server */
219         ipp_t           *request,       /* IPP Request */
220                         *response;      /* IPP Response */
221         cups_lang_t     *language;      /* Default language */
222         char            uri[HTTP_MAX_URI]; /* printer-uri attribute */
223
224
225         DEBUG(5,("cups_printername_ok(\"%s\")\n", name));
226
227        /*
228         * Make sure we don't ask for passwords...
229         */
230
231         cupsSetPasswordCB(cups_passwd_cb);
232
233        /*
234         * Try to connect to the server...
235         */
236
237         if ((http = httpConnect(cupsServer(), ippPort())) == NULL)
238         {
239                 DEBUG(0,("Unable to connect to CUPS server %s - %s\n", 
240                          cupsServer(), strerror(errno)));
241                 return (0);
242         }
243
244        /*
245         * Build an IPP_GET_PRINTER_ATTRS request, which requires the following
246         * attributes:
247         *
248         *    attributes-charset
249         *    attributes-natural-language
250         *    requested-attributes
251         *    printer-uri
252         */
253
254         request = ippNew();
255
256         request->request.op.operation_id = IPP_GET_PRINTER_ATTRIBUTES;
257         request->request.op.request_id   = 1;
258
259         language = cupsLangDefault();
260
261         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
262                      "attributes-charset", NULL, cupsLangEncoding(language));
263
264         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
265                      "attributes-natural-language", NULL, language->language);
266
267         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
268                      "requested-attributes", NULL, "printer-uri");
269
270         slprintf(uri, sizeof(uri) - 1, "ipp://localhost/printers/%s", name);
271
272         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
273                      "printer-uri", NULL, uri);
274
275        /*
276         * Do the request and get back a response...
277         */
278
279         if ((response = cupsDoRequest(http, request, "/")) == NULL)
280         {
281                 DEBUG(0,("Unable to get printer status for %s - %s\n", name,
282                          ippErrorString(cupsLastError())));
283                 httpClose(http);
284                 return (0);
285         }
286
287         httpClose(http);
288
289         if (response->request.status.status_code >= IPP_OK_CONFLICT)
290         {
291                 DEBUG(0,("Unable to get printer status for %s - %s\n", name,
292                          ippErrorString(response->request.status.status_code)));
293                 ippDelete(response);
294                 return (0);
295         }
296         else
297         {
298                 ippDelete(response);
299                 return (1);
300         }
301 }
302
303
304 /*
305  * 'cups_job_delete()' - Delete a job.
306  */
307
308 static int
309 cups_job_delete(int snum, struct printjob *pjob)
310 {
311         int             ret;            /* Return value */
312         http_t          *http;          /* HTTP connection to server */
313         ipp_t           *request,       /* IPP Request */
314                         *response;      /* IPP Response */
315         cups_lang_t     *language;      /* Default language */
316         char            uri[HTTP_MAX_URI]; /* printer-uri attribute */
317
318
319         DEBUG(5,("cups_job_delete(%d, %p (%d))\n", snum, pjob, pjob->sysjob));
320
321        /*
322         * Make sure we don't ask for passwords...
323         */
324
325         cupsSetPasswordCB(cups_passwd_cb);
326
327        /*
328         * Try to connect to the server...
329         */
330
331         if ((http = httpConnect(cupsServer(), ippPort())) == NULL)
332         {
333                 DEBUG(0,("Unable to connect to CUPS server %s - %s\n", 
334                          cupsServer(), strerror(errno)));
335                 return (1);
336         }
337
338        /*
339         * Build an IPP_CANCEL_JOB request, which requires the following
340         * attributes:
341         *
342         *    attributes-charset
343         *    attributes-natural-language
344         *    job-uri
345         *    requesting-user-name
346         */
347
348         request = ippNew();
349
350         request->request.op.operation_id = IPP_CANCEL_JOB;
351         request->request.op.request_id   = 1;
352
353         language = cupsLangDefault();
354
355         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
356                      "attributes-charset", NULL, cupsLangEncoding(language));
357
358         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
359                      "attributes-natural-language", NULL, language->language);
360
361         slprintf(uri, sizeof(uri) - 1, "ipp://localhost/jobs/%d", pjob->sysjob);
362
363         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri", NULL, uri);
364
365         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
366                      NULL, pjob->user);
367
368        /*
369         * Do the request and get back a response...
370         */
371
372         ret = 1;
373
374         if ((response = cupsDoRequest(http, request, "/jobs")) != NULL)
375         {
376           if (response->request.status.status_code >= IPP_OK_CONFLICT)
377                 DEBUG(0,("Unable to cancel job %d - %s\n", pjob->sysjob,
378                          ippErrorString(cupsLastError())));
379           else
380                 ret = 0;
381
382           ippDelete(response);
383         }
384         else
385           DEBUG(0,("Unable to cancel job %d - %s\n", pjob->sysjob,
386                    ippErrorString(cupsLastError())));
387
388         httpClose(http);
389
390         return (ret);
391 }
392
393
394 /*
395  * 'cups_job_pause()' - Pause a job.
396  */
397
398 static int
399 cups_job_pause(int snum, struct printjob *pjob)
400 {
401         int             ret;            /* Return value */
402         http_t          *http;          /* HTTP connection to server */
403         ipp_t           *request,       /* IPP Request */
404                         *response;      /* IPP Response */
405         cups_lang_t     *language;      /* Default language */
406         char            uri[HTTP_MAX_URI]; /* printer-uri attribute */
407
408
409         DEBUG(5,("cups_job_pause(%d, %p (%d))\n", snum, pjob, pjob->sysjob));
410
411        /*
412         * Make sure we don't ask for passwords...
413         */
414
415         cupsSetPasswordCB(cups_passwd_cb);
416
417        /*
418         * Try to connect to the server...
419         */
420
421         if ((http = httpConnect(cupsServer(), ippPort())) == NULL)
422         {
423                 DEBUG(0,("Unable to connect to CUPS server %s - %s\n", 
424                          cupsServer(), strerror(errno)));
425                 return (1);
426         }
427
428        /*
429         * Build an IPP_HOLD_JOB request, which requires the following
430         * attributes:
431         *
432         *    attributes-charset
433         *    attributes-natural-language
434         *    job-uri
435         *    requesting-user-name
436         */
437
438         request = ippNew();
439
440         request->request.op.operation_id = IPP_HOLD_JOB;
441         request->request.op.request_id   = 1;
442
443         language = cupsLangDefault();
444
445         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
446                      "attributes-charset", NULL, cupsLangEncoding(language));
447
448         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
449                      "attributes-natural-language", NULL, language->language);
450
451         slprintf(uri, sizeof(uri) - 1, "ipp://localhost/jobs/%d", pjob->sysjob);
452
453         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri", NULL, uri);
454
455         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
456                      NULL, pjob->user);
457
458        /*
459         * Do the request and get back a response...
460         */
461
462         ret = 1;
463
464         if ((response = cupsDoRequest(http, request, "/jobs")) != NULL)
465         {
466           if (response->request.status.status_code >= IPP_OK_CONFLICT)
467                 DEBUG(0,("Unable to hold job %d - %s\n", pjob->sysjob,
468                          ippErrorString(cupsLastError())));
469           else
470                 ret = 0;
471
472           ippDelete(response);
473         }
474         else
475           DEBUG(0,("Unable to hold job %d - %s\n", pjob->sysjob,
476                    ippErrorString(cupsLastError())));
477
478         httpClose(http);
479
480         return (ret);
481 }
482
483
484 /*
485  * 'cups_job_resume()' - Resume a paused job.
486  */
487
488 static int
489 cups_job_resume(int snum, struct printjob *pjob)
490 {
491         int             ret;            /* Return value */
492         http_t          *http;          /* HTTP connection to server */
493         ipp_t           *request,       /* IPP Request */
494                         *response;      /* IPP Response */
495         cups_lang_t     *language;      /* Default language */
496         char            uri[HTTP_MAX_URI]; /* printer-uri attribute */
497
498
499         DEBUG(5,("cups_job_resume(%d, %p (%d))\n", snum, pjob, pjob->sysjob));
500
501        /*
502         * Make sure we don't ask for passwords...
503         */
504
505         cupsSetPasswordCB(cups_passwd_cb);
506
507        /*
508         * Try to connect to the server...
509         */
510
511         if ((http = httpConnect(cupsServer(), ippPort())) == NULL)
512         {
513                 DEBUG(0,("Unable to connect to CUPS server %s - %s\n", 
514                          cupsServer(), strerror(errno)));
515                 return (1);
516         }
517
518        /*
519         * Build an IPP_RELEASE_JOB request, which requires the following
520         * attributes:
521         *
522         *    attributes-charset
523         *    attributes-natural-language
524         *    job-uri
525         *    requesting-user-name
526         */
527
528         request = ippNew();
529
530         request->request.op.operation_id = IPP_RELEASE_JOB;
531         request->request.op.request_id   = 1;
532
533         language = cupsLangDefault();
534
535         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
536                      "attributes-charset", NULL, cupsLangEncoding(language));
537
538         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
539                      "attributes-natural-language", NULL, language->language);
540
541         slprintf(uri, sizeof(uri) - 1, "ipp://localhost/jobs/%d", pjob->sysjob);
542
543         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri", NULL, uri);
544
545         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
546                      NULL, pjob->user);
547
548        /*
549         * Do the request and get back a response...
550         */
551
552         ret = 1;
553
554         if ((response = cupsDoRequest(http, request, "/jobs")) != NULL)
555         {
556           if (response->request.status.status_code >= IPP_OK_CONFLICT)
557                 DEBUG(0,("Unable to release job %d - %s\n", pjob->sysjob,
558                          ippErrorString(cupsLastError())));
559           else
560                 ret = 0;
561
562           ippDelete(response);
563         }
564         else
565           DEBUG(0,("Unable to release job %d - %s\n", pjob->sysjob,
566                    ippErrorString(cupsLastError())));
567
568         httpClose(http);
569
570         return (ret);
571 }
572
573
574 /*
575  * 'cups_job_submit()' - Submit a job for printing.
576  */
577
578 static int
579 cups_job_submit(int snum, struct printjob *pjob)
580 {
581         int             ret;            /* Return value */
582         http_t          *http;          /* HTTP connection to server */
583         ipp_t           *request,       /* IPP Request */
584                         *response;      /* IPP Response */
585         cups_lang_t     *language;      /* Default language */
586         char            uri[HTTP_MAX_URI]; /* printer-uri attribute */
587
588
589         DEBUG(5,("cups_job_submit(%d, %p (%d))\n", snum, pjob, pjob->sysjob));
590
591        /*
592         * Make sure we don't ask for passwords...
593         */
594
595         cupsSetPasswordCB(cups_passwd_cb);
596
597        /*
598         * Try to connect to the server...
599         */
600
601         if ((http = httpConnect(cupsServer(), ippPort())) == NULL)
602         {
603                 DEBUG(0,("Unable to connect to CUPS server %s - %s\n", 
604                          cupsServer(), strerror(errno)));
605                 return (1);
606         }
607
608        /*
609         * Build an IPP_PRINT_JOB request, which requires the following
610         * attributes:
611         *
612         *    attributes-charset
613         *    attributes-natural-language
614         *    printer-uri
615         *    requesting-user-name
616         *    [document-data]
617         */
618
619         request = ippNew();
620
621         request->request.op.operation_id = IPP_PRINT_JOB;
622         request->request.op.request_id   = 1;
623
624         language = cupsLangDefault();
625
626         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
627                      "attributes-charset", NULL, cupsLangEncoding(language));
628
629         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
630                      "attributes-natural-language", NULL, language->language);
631
632         slprintf(uri, sizeof(uri) - 1, "ipp://localhost/printers/%s",
633                  PRINTERNAME(snum));
634
635         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
636                      "printer-uri", NULL, uri);
637
638         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
639                      NULL, pjob->user);
640
641         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "job-name", NULL,
642                      pjob->jobname);
643
644        /*
645         * Do the request and get back a response...
646         */
647
648         slprintf(uri, sizeof(uri) - 1, "/printers/%s", PRINTERNAME(snum));
649
650         ret = 1;
651         if ((response = cupsDoFileRequest(http, request, uri,
652                                           pjob->filename)) != NULL)
653         {
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                 ippDelete(response);
661         }
662         else
663                 DEBUG(0,("Unable to print file to `%s' - %s\n", PRINTERNAME(snum),
664                          ippErrorString(cupsLastError())));
665
666         httpClose(http);
667
668         return (ret);
669 }
670
671
672 /*
673  * 'cups_queue_get()' - Get all the jobs in the print queue.
674  */
675
676 static int
677 cups_queue_get(int snum, print_queue_struct **q, print_status_struct *status)
678 {
679         http_t          *http;          /* HTTP connection to server */
680         ipp_t           *request,       /* IPP Request */
681                         *response;      /* IPP Response */
682         ipp_attribute_t *attr;          /* Current attribute */
683         cups_lang_t     *language;      /* Default language */
684         char            uri[HTTP_MAX_URI]; /* printer-uri attribute */
685         int             qcount,         /* Number of active queue entries */
686                         qalloc;         /* Number of queue entries allocated */
687         print_queue_struct *queue,      /* Queue entries */
688                         *temp;          /* Temporary pointer for queue */
689         const char      *user_name,     /* job-originating-user-name attribute */
690                         *job_name;      /* job-name attribute */
691         int             job_id;         /* job-id attribute */
692         int             job_k_octets;   /* job-k-octets attribute */
693         time_t          job_time;       /* time-at-creation attribute */
694         ipp_jstate_t    job_status;     /* job-status attribute */
695         int             job_priority;   /* job-priority attribute */
696         static const char *jattrs[] =   /* Requested job attributes */
697                         {
698                           "job-id",
699                           "job-k-octets",
700                           "job-name",
701                           "job-originating-user-name",
702                           "job-priority",
703                           "job-state",
704                           "time-at-creation",
705                         };
706         static const char *pattrs[] =   /* Requested printer attributes */
707                         {
708                           "printer-state",
709                           "printer-state-message"
710                         };
711
712
713         DEBUG(5,("cups_queue_get(%d, %p, %p)\n", snum, q, status));
714
715        /*
716         * Make sure we don't ask for passwords...
717         */
718
719         cupsSetPasswordCB(cups_passwd_cb);
720
721        /*
722         * Try to connect to the server...
723         */
724
725         if ((http = httpConnect(cupsServer(), ippPort())) == NULL)
726         {
727                 DEBUG(0,("Unable to connect to CUPS server %s - %s\n", 
728                          cupsServer(), strerror(errno)));
729                 return (0);
730         }
731
732        /*
733         * Generate the printer URI...
734         */
735
736         slprintf(uri, sizeof(uri) - 1, "ipp://localhost/printers/%s",
737                  PRINTERNAME(snum));
738
739        /*
740         * Build an IPP_GET_JOBS request, which requires the following
741         * attributes:
742         *
743         *    attributes-charset
744         *    attributes-natural-language
745         *    requested-attributes
746         *    printer-uri
747         */
748
749         request = ippNew();
750
751         request->request.op.operation_id = IPP_GET_JOBS;
752         request->request.op.request_id   = 1;
753
754         language = cupsLangDefault();
755
756         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
757                      "attributes-charset", NULL, cupsLangEncoding(language));
758
759         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
760                      "attributes-natural-language", NULL, language->language);
761
762         ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
763                       "requested-attributes",
764                       (sizeof(jattrs) / sizeof(jattrs[0])),
765                       NULL, jattrs);
766
767         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
768                      "printer-uri", NULL, uri);
769
770        /*
771         * Do the request and get back a response...
772         */
773
774         if ((response = cupsDoRequest(http, request, "/")) == NULL)
775         {
776                 DEBUG(0,("Unable to get jobs for %s - %s\n", uri,
777                          ippErrorString(cupsLastError())));
778                 httpClose(http);
779                 return (0);
780         }
781
782         if (response->request.status.status_code >= IPP_OK_CONFLICT)
783         {
784                 DEBUG(0,("Unable to get jobs for %s - %s\n", uri,
785                          ippErrorString(response->request.status.status_code)));
786                 ippDelete(response);
787                 httpClose(http);
788
789                 return (0);
790         }
791
792        /*
793         * Process the jobs...
794         */
795
796         qcount = 0;
797         qalloc = 0;
798         queue  = NULL;
799
800         for (attr = response->attrs; attr != NULL; attr = attr->next)
801         {
802                /*
803                 * Skip leading attributes until we hit a job...
804                 */
805
806                 while (attr != NULL && attr->group_tag != IPP_TAG_JOB)
807                         attr = attr->next;
808
809                 if (attr == NULL)
810                         break;
811
812                /*
813                 * Allocate memory as needed...
814                 */
815                 if (qcount >= qalloc)
816                 {
817                         qalloc += 16;
818
819                         temp = Realloc(queue, sizeof(print_queue_struct) * qalloc);
820
821                         if (temp == NULL)
822                         {
823                                 DEBUG(0,("cups_queue_get: Not enough memory!"));
824                                 ippDelete(response);
825                                 httpClose(http);
826
827                                 free (queue);
828                                 return (0);
829                         }
830
831                         queue = temp;
832                 }
833
834                 temp = queue + qcount;
835                 memset(temp, 0, sizeof(print_queue_struct));
836
837                /*
838                 * Pull the needed attributes from this job...
839                 */
840
841                 job_id       = 0;
842                 job_priority = 50;
843                 job_status   = IPP_JOB_PENDING;
844                 job_time     = 0;
845                 job_k_octets = 0;
846                 user_name    = NULL;
847                 job_name     = NULL;
848
849                 while (attr != NULL && attr->group_tag == IPP_TAG_JOB)
850                 {
851                         if (attr->name == NULL)
852                         {
853                                 attr = attr->next;
854                                 break;
855                         }
856
857                         if (strcmp(attr->name, "job-id") == 0 &&
858                             attr->value_tag == IPP_TAG_INTEGER)
859                                 job_id = attr->values[0].integer;
860
861                         if (strcmp(attr->name, "job-k-octets") == 0 &&
862                             attr->value_tag == IPP_TAG_INTEGER)
863                                 job_k_octets = attr->values[0].integer;
864
865                         if (strcmp(attr->name, "job-priority") == 0 &&
866                             attr->value_tag == IPP_TAG_INTEGER)
867                                 job_priority = attr->values[0].integer;
868
869                         if (strcmp(attr->name, "job-state") == 0 &&
870                             attr->value_tag == IPP_TAG_ENUM)
871                                 job_status = (ipp_jstate_t)(attr->values[0].integer);
872
873                         if (strcmp(attr->name, "time-at-creation") == 0 &&
874                             attr->value_tag == IPP_TAG_INTEGER)
875                                 job_time = attr->values[0].integer;
876
877                         if (strcmp(attr->name, "job-name") == 0 &&
878                             attr->value_tag == IPP_TAG_NAME)
879                                 job_name = attr->values[0].string.text;
880
881                         if (strcmp(attr->name, "job-originating-user-name") == 0 &&
882                             attr->value_tag == IPP_TAG_NAME)
883                                 user_name = attr->values[0].string.text;
884
885                         attr = attr->next;
886                 }
887
888                /*
889                 * See if we have everything needed...
890                 */
891
892                 if (user_name == NULL || job_name == NULL || job_id == 0)
893                 {
894                   if (attr == NULL)
895                     break;
896                   else
897                     continue;
898                 }
899
900                 temp->job      = job_id;
901                 temp->size     = job_k_octets * 1024;
902                 temp->status   = job_status == IPP_JOB_PENDING ? LPQ_QUEUED :
903                                  job_status == IPP_JOB_STOPPED ? LPQ_PAUSED :
904                                  job_status == IPP_JOB_HELD ? LPQ_PAUSED :
905                                  LPQ_PRINTING;
906                 temp->priority = job_priority;
907                 temp->time     = job_time;
908                 strncpy(temp->user, user_name, sizeof(temp->user) - 1);
909                 strncpy(temp->file, job_name, sizeof(temp->file) - 1);
910
911                 qcount ++;
912
913                 if (attr == NULL)
914                   break;
915         }
916
917         ippDelete(response);
918
919        /*
920         * Build an IPP_GET_PRINTER_ATTRIBUTES request, which requires the
921         * following attributes:
922         *
923         *    attributes-charset
924         *    attributes-natural-language
925         *    requested-attributes
926         *    printer-uri
927         */
928
929         request = ippNew();
930
931         request->request.op.operation_id = IPP_GET_PRINTER_ATTRIBUTES;
932         request->request.op.request_id   = 1;
933
934         language = cupsLangDefault();
935
936         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
937                      "attributes-charset", NULL, cupsLangEncoding(language));
938
939         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
940                      "attributes-natural-language", NULL, language->language);
941
942         ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
943                       "requested-attributes",
944                       (sizeof(pattrs) / sizeof(pattrs[0])),
945                       NULL, pattrs);
946
947         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
948                      "printer-uri", NULL, uri);
949
950        /*
951         * Do the request and get back a response...
952         */
953
954         if ((response = cupsDoRequest(http, request, "/")) == NULL)
955         {
956                 DEBUG(0,("Unable to get printer status for %s - %s\n", PRINTERNAME(snum),
957                          ippErrorString(cupsLastError())));
958                 httpClose(http);
959                 *q = queue;
960                 return (qcount);
961         }
962
963         if (response->request.status.status_code >= IPP_OK_CONFLICT)
964         {
965                 DEBUG(0,("Unable to get printer status for %s - %s\n", PRINTERNAME(snum),
966                          ippErrorString(response->request.status.status_code)));
967                 ippDelete(response);
968                 httpClose(http);
969                 *q = queue;
970                 return (qcount);
971         }
972
973        /*
974         * Get the current printer status and convert it to the SAMBA values.
975         */
976
977         if ((attr = ippFindAttribute(response, "printer-state", IPP_TAG_ENUM)) != NULL)
978         {
979                 if (attr->values[0].integer == IPP_PRINTER_STOPPED)
980                         status->status = LPSTAT_STOPPED;
981                 else
982                         status->status = LPSTAT_OK;
983         }
984
985         if ((attr = ippFindAttribute(response, "printer-state-message",
986                                      IPP_TAG_TEXT)) != NULL)
987                 fstrcpy(status->message, attr->values[0].string.text);
988
989         ippDelete(response);
990
991        /*
992         * Return the job queue...
993         */
994
995         httpClose(http);
996
997         *q = queue;
998         return (qcount);
999 }
1000
1001
1002 /*
1003  * 'cups_queue_pause()' - Pause a print queue.
1004  */
1005
1006 static int
1007 cups_queue_pause(int snum)
1008 {
1009         extern userdom_struct current_user_info;
1010         int             ret;            /* Return value */
1011         http_t          *http;          /* HTTP connection to server */
1012         ipp_t           *request,       /* IPP Request */
1013                         *response;      /* IPP Response */
1014         cups_lang_t     *language;      /* 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 = httpConnect(cupsServer(), ippPort())) == NULL)
1031         {
1032                 DEBUG(0,("Unable to connect to CUPS server %s - %s\n", 
1033                          cupsServer(), strerror(errno)));
1034                 return (1);
1035         }
1036
1037         /*
1038          * Build an IPP_PAUSE_PRINTER request, which requires the following
1039          * attributes:
1040          *
1041          *    attributes-charset
1042          *    attributes-natural-language
1043          *    printer-uri
1044          *    requesting-user-name
1045          */
1046
1047         request = ippNew();
1048
1049         request->request.op.operation_id = IPP_PAUSE_PRINTER;
1050         request->request.op.request_id   = 1;
1051
1052         language = cupsLangDefault();
1053
1054         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
1055                      "attributes-charset", NULL, cupsLangEncoding(language));
1056
1057         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
1058                      "attributes-natural-language", NULL, language->language);
1059
1060         slprintf(uri, sizeof(uri) - 1, "ipp://localhost/printers/%s",
1061                  PRINTERNAME(snum));
1062
1063         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, uri);
1064
1065         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
1066                      NULL, current_user_info.unix_name);
1067
1068        /*
1069         * Do the request and get back a response...
1070         */
1071
1072         ret = 1;
1073
1074         if ((response = cupsDoRequest(http, request, "/admin/")) != NULL)
1075         {
1076           if (response->request.status.status_code >= IPP_OK_CONFLICT)
1077                 DEBUG(0,("Unable to pause printer %s - %s\n", PRINTERNAME(snum),
1078                          ippErrorString(cupsLastError())));
1079           else
1080                 ret = 0;
1081
1082           ippDelete(response);
1083         }
1084         else
1085           DEBUG(0,("Unable to pause printer %s - %s\n", PRINTERNAME(snum),
1086                    ippErrorString(cupsLastError())));
1087
1088         httpClose(http);
1089
1090         return (ret);
1091 }
1092
1093
1094 /*
1095  * 'cups_queue_resume()' - Restart a print queue.
1096  */
1097
1098 static int
1099 cups_queue_resume(int snum)
1100 {
1101         extern userdom_struct current_user_info;
1102         int             ret;            /* Return value */
1103         http_t          *http;          /* HTTP connection to server */
1104         ipp_t           *request,       /* IPP Request */
1105                         *response;      /* IPP Response */
1106         cups_lang_t     *language;      /* Default language */
1107         char            uri[HTTP_MAX_URI]; /* printer-uri attribute */
1108
1109
1110         DEBUG(5,("cups_queue_resume(%d)\n", snum));
1111
1112        /*
1113         * Make sure we don't ask for passwords...
1114         */
1115
1116         cupsSetPasswordCB(cups_passwd_cb);
1117
1118        /*
1119         * Try to connect to the server...
1120         */
1121
1122         if ((http = httpConnect(cupsServer(), ippPort())) == NULL)
1123         {
1124                 DEBUG(0,("Unable to connect to CUPS server %s - %s\n", 
1125                          cupsServer(), strerror(errno)));
1126                 return (1);
1127         }
1128
1129        /*
1130         * Build an IPP_RESUME_PRINTER request, which requires the following
1131         * attributes:
1132         *
1133         *    attributes-charset
1134         *    attributes-natural-language
1135         *    printer-uri
1136         *    requesting-user-name
1137         */
1138
1139         request = ippNew();
1140
1141         request->request.op.operation_id = IPP_RESUME_PRINTER;
1142         request->request.op.request_id   = 1;
1143
1144         language = cupsLangDefault();
1145
1146         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
1147                      "attributes-charset", NULL, cupsLangEncoding(language));
1148
1149         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
1150                      "attributes-natural-language", NULL, language->language);
1151
1152         slprintf(uri, sizeof(uri) - 1, "ipp://localhost/printers/%s",
1153                  PRINTERNAME(snum));
1154
1155         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, uri);
1156
1157         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
1158                      NULL, current_user_info.unix_name);
1159
1160        /*
1161         * Do the request and get back a response...
1162         */
1163
1164         ret = 1;
1165
1166         if ((response = cupsDoRequest(http, request, "/admin/")) != NULL)
1167         {
1168           if (response->request.status.status_code >= IPP_OK_CONFLICT)
1169                 DEBUG(0,("Unable to resume printer %s - %s\n", PRINTERNAME(snum),
1170                          ippErrorString(cupsLastError())));
1171           else
1172                 ret = 0;
1173
1174           ippDelete(response);
1175         }
1176         else
1177           DEBUG(0,("Unable to resume printer %s - %s\n", PRINTERNAME(snum),
1178                    ippErrorString(cupsLastError())));
1179
1180         httpClose(http);
1181
1182         return (ret);
1183 }
1184
1185
1186 #else
1187  /* this keeps fussy compilers happy */
1188  void print_cups_dummy(void) {}
1189 #endif /* HAVE_CUPS */