source: trunk/samba/source/printing/print_cups.c @ 26

Last change on this file since 26 was 26, checked in by Paul Smedley, 14 years ago

Updated source to 3.0.25rc1

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