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