root/source3/printing/print_cups.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. gotalarm_sig
  2. cups_passwd_cb
  3. cups_connect
  4. send_pcap_info
  5. cups_cache_reload_async
  6. cups_pcap_load_async
  7. cups_async_callback
  8. cups_cache_reload
  9. cups_job_delete
  10. cups_job_pause
  11. cups_job_resume
  12. cups_job_submit
  13. cups_queue_get
  14. cups_queue_pause
  15. cups_queue_resume
  16. cups_pull_comment_location
  17. print_cups_dummy

   1 /*
   2  * Support code for the Common UNIX Printing System ("CUPS")
   3  *
   4  * Copyright 1999-2003 by Michael R Sweet.
   5  * Copyright 2008 Jeremy Allison.
   6  *
   7  * This program is free software; you can redistribute it and/or modify
   8  * it under the terms of the GNU General Public License as published by
   9  * the Free Software Foundation; either version 3 of the License, or
  10  * (at your option) any later version.
  11  *
  12  * This program is distributed in the hope that it will be useful,
  13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15  * GNU General Public License for more details.
  16  *
  17  * You should have received a copy of the GNU General Public License
  18  * along with this program; if not, see <http://www.gnu.org/licenses/>.
  19  */
  20 
  21 /*
  22  * JRA. Converted to utf8 pull/push.
  23  */
  24 
  25 #include "includes.h"
  26 #include "printing.h"
  27 
  28 #ifdef HAVE_CUPS
  29 #include <cups/cups.h>
  30 #include <cups/language.h>
  31 
  32 static SIG_ATOMIC_T gotalarm;
  33 
  34 /***************************************************************
  35  Signal function to tell us we timed out.
  36 ****************************************************************/
  37 
  38 static void gotalarm_sig(void)
     /* [<][>][^][v][top][bottom][index][help] */
  39 {
  40         gotalarm = 1;
  41 }
  42 
  43 extern userdom_struct current_user_info;
  44 
  45 /*
  46  * 'cups_passwd_cb()' - The CUPS password callback...
  47  */
  48 
  49 static const char *                             /* O - Password or NULL */
  50 cups_passwd_cb(const char *prompt)      /* I - Prompt */
     /* [<][>][^][v][top][bottom][index][help] */
  51 {
  52         /*
  53          * Always return NULL to indicate that no password is available...
  54          */
  55 
  56         return (NULL);
  57 }
  58 
  59 static http_t *cups_connect(TALLOC_CTX *frame)
     /* [<][>][^][v][top][bottom][index][help] */
  60 {
  61         http_t *http = NULL;
  62         char *server = NULL, *p = NULL;
  63         int port;
  64         int timeout = lp_cups_connection_timeout();
  65         size_t size;
  66 
  67         if (lp_cups_server() != NULL && strlen(lp_cups_server()) > 0) {
  68                 if (!push_utf8_talloc(frame, &server, lp_cups_server(), &size)) {
  69                         return NULL;
  70                 }
  71         } else {
  72                 server = talloc_strdup(frame,cupsServer());
  73         }
  74         if (!server) {
  75                 return NULL;
  76         }
  77 
  78         p = strchr(server, ':');
  79         if (p) {
  80                 port = atoi(p+1);
  81                 *p = '\0';
  82         } else {
  83                 port = ippPort();
  84         }
  85 
  86         DEBUG(10, ("connecting to cups server %s:%d\n",
  87                    server, port));
  88 
  89         gotalarm = 0;
  90 
  91         if (timeout) {
  92                 CatchSignal(SIGALRM, SIGNAL_CAST gotalarm_sig);
  93                 alarm(timeout);
  94         }
  95 
  96         http = httpConnect(server, port);
  97 
  98         CatchSignal(SIGALRM, SIGNAL_CAST SIG_IGN);
  99         alarm(0);
 100 
 101         if (http == NULL) {
 102                 DEBUG(0,("Unable to connect to CUPS server %s:%d - %s\n",
 103                          server, port, strerror(errno)));
 104         }
 105 
 106         return http;
 107 }
 108 
 109 static void send_pcap_info(const char *name, const char *info, void *pd)
     /* [<][>][^][v][top][bottom][index][help] */
 110 {
 111         int fd = *(int *)pd;
 112         size_t namelen = name ? strlen(name)+1 : 0;
 113         size_t infolen = info ? strlen(info)+1 : 0;
 114 
 115         DEBUG(11,("send_pcap_info: writing namelen %u\n", (unsigned int)namelen));
 116         if (sys_write(fd, &namelen, sizeof(namelen)) != sizeof(namelen)) {
 117                 DEBUG(10,("send_pcap_info: namelen write failed %s\n",
 118                         strerror(errno)));
 119                 return;
 120         }
 121         DEBUG(11,("send_pcap_info: writing infolen %u\n", (unsigned int)infolen));
 122         if (sys_write(fd, &infolen, sizeof(infolen)) != sizeof(infolen)) {
 123                 DEBUG(10,("send_pcap_info: infolen write failed %s\n",
 124                         strerror(errno)));
 125                 return;
 126         }
 127         if (namelen) {
 128                 DEBUG(11,("send_pcap_info: writing name %s\n", name));
 129                 if (sys_write(fd, name, namelen) != namelen) {
 130                         DEBUG(10,("send_pcap_info: name write failed %s\n",
 131                                 strerror(errno)));
 132                         return;
 133                 }
 134         }
 135         if (infolen) {
 136                 DEBUG(11,("send_pcap_info: writing info %s\n", info));
 137                 if (sys_write(fd, info, infolen) != infolen) {
 138                         DEBUG(10,("send_pcap_info: info write failed %s\n",
 139                                 strerror(errno)));
 140                         return;
 141                 }
 142         }
 143 }
 144 
 145 static bool cups_cache_reload_async(int fd)
     /* [<][>][^][v][top][bottom][index][help] */
 146 {
 147         TALLOC_CTX *frame = talloc_stackframe();
 148         struct pcap_cache *tmp_pcap_cache = NULL;
 149         http_t          *http = NULL;           /* HTTP connection to server */
 150         ipp_t           *request = NULL,        /* IPP Request */
 151                         *response = NULL;       /* IPP Response */
 152         ipp_attribute_t *attr;          /* Current attribute */
 153         cups_lang_t     *language = NULL;       /* Default language */
 154         char            *name,          /* printer-name attribute */
 155                         *info;          /* printer-info attribute */
 156         static const char *requested[] =/* Requested attributes */
 157                         {
 158                           "printer-name",
 159                           "printer-info"
 160                         };
 161         bool ret = False;
 162         size_t size;
 163 
 164         DEBUG(5, ("reloading cups printcap cache\n"));
 165 
 166        /*
 167         * Make sure we don't ask for passwords...
 168         */
 169 
 170         cupsSetPasswordCB(cups_passwd_cb);
 171 
 172        /*
 173         * Try to connect to the server...
 174         */
 175 
 176         if ((http = cups_connect(frame)) == NULL) {
 177                 goto out;
 178         }
 179 
 180        /*
 181         * Build a CUPS_GET_PRINTERS request, which requires the following
 182         * attributes:
 183         *
 184         *    attributes-charset
 185         *    attributes-natural-language
 186         *    requested-attributes
 187         */
 188 
 189         request = ippNew();
 190 
 191         request->request.op.operation_id = CUPS_GET_PRINTERS;
 192         request->request.op.request_id   = 1;
 193 
 194         language = cupsLangDefault();
 195 
 196         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
 197                      "attributes-charset", NULL, "utf-8");
 198 
 199         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
 200                      "attributes-natural-language", NULL, language->language);
 201 
 202         ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
 203                       "requested-attributes",
 204                       (sizeof(requested) / sizeof(requested[0])),
 205                       NULL, requested);
 206 
 207        /*
 208         * Do the request and get back a response...
 209         */
 210 
 211         if ((response = cupsDoRequest(http, request, "/")) == NULL) {
 212                 DEBUG(0,("Unable to get printer list - %s\n",
 213                          ippErrorString(cupsLastError())));
 214                 goto out;
 215         }
 216 
 217         for (attr = response->attrs; attr != NULL;) {
 218                /*
 219                 * Skip leading attributes until we hit a printer...
 220                 */
 221 
 222                 while (attr != NULL && attr->group_tag != IPP_TAG_PRINTER)
 223                         attr = attr->next;
 224 
 225                 if (attr == NULL)
 226                         break;
 227 
 228                /*
 229                 * Pull the needed attributes from this printer...
 230                 */
 231 
 232                 name       = NULL;
 233                 info       = NULL;
 234 
 235                 while (attr != NULL && attr->group_tag == IPP_TAG_PRINTER) {
 236                         if (strcmp(attr->name, "printer-name") == 0 &&
 237                             attr->value_tag == IPP_TAG_NAME) {
 238                                 if (!pull_utf8_talloc(frame,
 239                                                 &name,
 240                                                 attr->values[0].string.text,
 241                                                 &size)) {
 242                                         goto out;
 243                                 }
 244                         }
 245 
 246                         if (strcmp(attr->name, "printer-info") == 0 &&
 247                             attr->value_tag == IPP_TAG_TEXT) {
 248                                 if (!pull_utf8_talloc(frame,
 249                                                 &info,
 250                                                 attr->values[0].string.text,
 251                                                 &size)) {
 252                                         goto out;
 253                                 }
 254                         }
 255 
 256                         attr = attr->next;
 257                 }
 258 
 259                /*
 260                 * See if we have everything needed...
 261                 */
 262 
 263                 if (name == NULL)
 264                         break;
 265 
 266                 if (!pcap_cache_add_specific(&tmp_pcap_cache, name, info)) {
 267                         goto out;
 268                 }
 269         }
 270 
 271         ippDelete(response);
 272         response = NULL;
 273 
 274        /*
 275         * Build a CUPS_GET_CLASSES request, which requires the following
 276         * attributes:
 277         *
 278         *    attributes-charset
 279         *    attributes-natural-language
 280         *    requested-attributes
 281         */
 282 
 283         request = ippNew();
 284 
 285         request->request.op.operation_id = CUPS_GET_CLASSES;
 286         request->request.op.request_id   = 1;
 287 
 288         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
 289                      "attributes-charset", NULL, "utf-8");
 290 
 291         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
 292                      "attributes-natural-language", NULL, language->language);
 293 
 294         ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
 295                       "requested-attributes",
 296                       (sizeof(requested) / sizeof(requested[0])),
 297                       NULL, requested);
 298 
 299        /*
 300         * Do the request and get back a response...
 301         */
 302 
 303         if ((response = cupsDoRequest(http, request, "/")) == NULL) {
 304                 DEBUG(0,("Unable to get printer list - %s\n",
 305                          ippErrorString(cupsLastError())));
 306                 goto out;
 307         }
 308 
 309         for (attr = response->attrs; attr != NULL;) {
 310                /*
 311                 * Skip leading attributes until we hit a printer...
 312                 */
 313 
 314                 while (attr != NULL && attr->group_tag != IPP_TAG_PRINTER)
 315                         attr = attr->next;
 316 
 317                 if (attr == NULL)
 318                         break;
 319 
 320                /*
 321                 * Pull the needed attributes from this printer...
 322                 */
 323 
 324                 name       = NULL;
 325                 info       = NULL;
 326 
 327                 while (attr != NULL && attr->group_tag == IPP_TAG_PRINTER) {
 328                         if (strcmp(attr->name, "printer-name") == 0 &&
 329                             attr->value_tag == IPP_TAG_NAME) {
 330                                 if (!pull_utf8_talloc(frame,
 331                                                 &name,
 332                                                 attr->values[0].string.text,
 333                                                 &size)) {
 334                                         goto out;
 335                                 }
 336                         }
 337 
 338                         if (strcmp(attr->name, "printer-info") == 0 &&
 339                             attr->value_tag == IPP_TAG_TEXT) {
 340                                 if (!pull_utf8_talloc(frame,
 341                                                 &info,
 342                                                 attr->values[0].string.text,
 343                                                 &size)) {
 344                                         goto out;
 345                                 }
 346                         }
 347 
 348                         attr = attr->next;
 349                 }
 350 
 351                /*
 352                 * See if we have everything needed...
 353                 */
 354 
 355                 if (name == NULL)
 356                         break;
 357 
 358                 if (!pcap_cache_add_specific(&tmp_pcap_cache, name, info)) {
 359                         goto out;
 360                 }
 361         }
 362 
 363         ret = True;
 364 
 365  out:
 366         if (response)
 367                 ippDelete(response);
 368 
 369         if (language)
 370                 cupsLangFree(language);
 371 
 372         if (http)
 373                 httpClose(http);
 374 
 375         /* Send all the entries up the pipe. */
 376         if (tmp_pcap_cache) {
 377                 pcap_printer_fn_specific(tmp_pcap_cache,
 378                                 send_pcap_info,
 379                                 (void *)&fd);
 380 
 381                 pcap_cache_destroy_specific(&tmp_pcap_cache);
 382         }
 383         TALLOC_FREE(frame);
 384         return ret;
 385 }
 386 
 387 static struct pcap_cache *local_pcap_copy;
 388 struct fd_event *cache_fd_event;
 389 
 390 static bool cups_pcap_load_async(int *pfd)
     /* [<][>][^][v][top][bottom][index][help] */
 391 {
 392         int fds[2];
 393         pid_t pid;
 394 
 395         *pfd = -1;
 396 
 397         if (cache_fd_event) {
 398                 DEBUG(3,("cups_pcap_load_async: already waiting for "
 399                         "a refresh event\n" ));
 400                 return false;
 401         }
 402 
 403         DEBUG(5,("cups_pcap_load_async: asynchronously loading cups printers\n"));
 404 
 405         if (pipe(fds) == -1) {
 406                 return false;
 407         }
 408 
 409         pid = sys_fork();
 410         if (pid == (pid_t)-1) {
 411                 DEBUG(10,("cups_pcap_load_async: fork failed %s\n",
 412                         strerror(errno) ));
 413                 close(fds[0]);
 414                 close(fds[1]);
 415                 return false;
 416         }
 417 
 418         if (pid) {
 419                 DEBUG(10,("cups_pcap_load_async: child pid = %u\n",
 420                         (unsigned int)pid ));
 421                 /* Parent. */
 422                 close(fds[1]);
 423                 *pfd = fds[0];
 424                 return true;
 425         }
 426 
 427         /* Child. */
 428 
 429         close_all_print_db();
 430 
 431         if (!NT_STATUS_IS_OK(reinit_after_fork(smbd_messaging_context(),
 432                                                smbd_event_context(), true))) {
 433                 DEBUG(0,("cups_pcap_load_async: reinit_after_fork() failed\n"));
 434                 smb_panic("cups_pcap_load_async: reinit_after_fork() failed");
 435         }
 436 
 437         close(fds[0]);
 438         cups_cache_reload_async(fds[1]);
 439         close(fds[1]);
 440         _exit(0);
 441 }
 442 
 443 static void cups_async_callback(struct event_context *event_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 444                                 struct fd_event *event,
 445                                 uint16 flags,
 446                                 void *p)
 447 {
 448         TALLOC_CTX *frame = talloc_stackframe();
 449         int fd = *(int *)p;
 450         struct pcap_cache *tmp_pcap_cache = NULL;
 451 
 452         DEBUG(5,("cups_async_callback: callback received for printer data. "
 453                 "fd = %d\n", fd));
 454 
 455         while (1) {
 456                 char *name = NULL, *info = NULL;
 457                 size_t namelen = 0, infolen = 0;
 458                 ssize_t ret = -1;
 459 
 460                 ret = sys_read(fd, &namelen, sizeof(namelen));
 461                 if (ret == 0) {
 462                         /* EOF */
 463                         break;
 464                 }
 465                 if (ret != sizeof(namelen)) {
 466                         DEBUG(10,("cups_async_callback: namelen read failed %d %s\n",
 467                                 errno, strerror(errno)));
 468                         break;
 469                 }
 470 
 471                 DEBUG(11,("cups_async_callback: read namelen %u\n",
 472                         (unsigned int)namelen));
 473 
 474                 ret = sys_read(fd, &infolen, sizeof(infolen));
 475                 if (ret == 0) {
 476                         /* EOF */
 477                         break;
 478                 }
 479                 if (ret != sizeof(infolen)) {
 480                         DEBUG(10,("cups_async_callback: infolen read failed %s\n",
 481                                 strerror(errno)));
 482                         break;
 483                 }
 484 
 485                 DEBUG(11,("cups_async_callback: read infolen %u\n",
 486                         (unsigned int)infolen));
 487 
 488                 if (namelen) {
 489                         name = TALLOC_ARRAY(frame, char, namelen);
 490                         if (!name) {
 491                                 break;
 492                         }
 493                         ret = sys_read(fd, name, namelen);
 494                         if (ret == 0) {
 495                                 /* EOF */
 496                                 break;
 497                         }
 498                         if (ret != namelen) {
 499                                 DEBUG(10,("cups_async_callback: name read failed %s\n",
 500                                         strerror(errno)));
 501                                 break;
 502                         }
 503                         DEBUG(11,("cups_async_callback: read name %s\n",
 504                                 name));
 505                 } else {
 506                         name = NULL;
 507                 }
 508                 if (infolen) {
 509                         info = TALLOC_ARRAY(frame, char, infolen);
 510                         if (!info) {
 511                                 break;
 512                         }
 513                         ret = sys_read(fd, info, infolen);
 514                         if (ret == 0) {
 515                                 /* EOF */
 516                                 break;
 517                         }
 518                         if (ret != infolen) {
 519                                 DEBUG(10,("cups_async_callback: info read failed %s\n",
 520                                         strerror(errno)));
 521                                 break;
 522                         }
 523                         DEBUG(11,("cups_async_callback: read info %s\n",
 524                                 info));
 525                 } else {
 526                         info = NULL;
 527                 }
 528 
 529                 /* Add to our local pcap cache. */
 530                 pcap_cache_add_specific(&tmp_pcap_cache, name, info);
 531                 TALLOC_FREE(name);
 532                 TALLOC_FREE(info);
 533         }
 534 
 535         TALLOC_FREE(frame);
 536         if (tmp_pcap_cache) {
 537                 /* We got a namelist, replace our local cache. */
 538                 pcap_cache_destroy_specific(&local_pcap_copy);
 539                 local_pcap_copy = tmp_pcap_cache;
 540 
 541                 /* And the systemwide pcap cache. */
 542                 pcap_cache_replace(local_pcap_copy);
 543         } else {
 544                 DEBUG(2,("cups_async_callback: failed to read a new "
 545                         "printer list\n"));
 546         }
 547         close(fd);
 548         TALLOC_FREE(p);
 549         TALLOC_FREE(cache_fd_event);
 550 }
 551 
 552 bool cups_cache_reload(void)
     /* [<][>][^][v][top][bottom][index][help] */
 553 {
 554         int *p_pipe_fd = TALLOC_P(NULL, int);
 555 
 556         if (!p_pipe_fd) {
 557                 return false;
 558         }
 559 
 560         *p_pipe_fd = -1;
 561 
 562         /* Set up an async refresh. */
 563         if (!cups_pcap_load_async(p_pipe_fd)) {
 564                 return false;
 565         }
 566         if (!local_pcap_copy) {
 567                 /* We have no local cache, wait directly for
 568                  * async refresh to complete.
 569                  */
 570                 DEBUG(10,("cups_cache_reload: sync read on fd %d\n",
 571                         *p_pipe_fd ));
 572 
 573                 cups_async_callback(smbd_event_context(),
 574                                         NULL,
 575                                         EVENT_FD_READ,
 576                                         (void *)p_pipe_fd);
 577                 if (!local_pcap_copy) {
 578                         return false;
 579                 }
 580         } else {
 581                 /* Replace the system cache with our
 582                  * local copy. */
 583                 pcap_cache_replace(local_pcap_copy);
 584 
 585                 DEBUG(10,("cups_cache_reload: async read on fd %d\n",
 586                         *p_pipe_fd ));
 587 
 588                 /* Trigger an event when the pipe can be read. */
 589                 cache_fd_event = event_add_fd(smbd_event_context(),
 590                                         NULL, *p_pipe_fd,
 591                                         EVENT_FD_READ,
 592                                         cups_async_callback,
 593                                         (void *)p_pipe_fd);
 594                 if (!cache_fd_event) {
 595                         close(*p_pipe_fd);
 596                         TALLOC_FREE(p_pipe_fd);
 597                         return false;
 598                 }
 599         }
 600         return true;
 601 }
 602 
 603 /*
 604  * 'cups_job_delete()' - Delete a job.
 605  */
 606 
 607 static int cups_job_delete(const char *sharename, const char *lprm_command, struct printjob *pjob)
     /* [<][>][^][v][top][bottom][index][help] */
 608 {
 609         TALLOC_CTX *frame = talloc_stackframe();
 610         int             ret = 1;                /* Return value */
 611         http_t          *http = NULL;           /* HTTP connection to server */
 612         ipp_t           *request = NULL,        /* IPP Request */
 613                         *response = NULL;       /* IPP Response */
 614         cups_lang_t     *language = NULL;       /* Default language */
 615         char *user = NULL;
 616         char            uri[HTTP_MAX_URI]; /* printer-uri attribute */
 617         size_t size;
 618 
 619         DEBUG(5,("cups_job_delete(%s, %p (%d))\n", sharename, pjob, pjob->sysjob));
 620 
 621        /*
 622         * Make sure we don't ask for passwords...
 623         */
 624 
 625         cupsSetPasswordCB(cups_passwd_cb);
 626 
 627        /*
 628         * Try to connect to the server...
 629         */
 630 
 631         if ((http = cups_connect(frame)) == NULL) {
 632                 goto out;
 633         }
 634 
 635        /*
 636         * Build an IPP_CANCEL_JOB request, which requires the following
 637         * attributes:
 638         *
 639         *    attributes-charset
 640         *    attributes-natural-language
 641         *    job-uri
 642         *    requesting-user-name
 643         */
 644 
 645         request = ippNew();
 646 
 647         request->request.op.operation_id = IPP_CANCEL_JOB;
 648         request->request.op.request_id   = 1;
 649 
 650         language = cupsLangDefault();
 651 
 652         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
 653                      "attributes-charset", NULL, "utf-8");
 654 
 655         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
 656                      "attributes-natural-language", NULL, language->language);
 657 
 658         slprintf(uri, sizeof(uri) - 1, "ipp://localhost/jobs/%d", pjob->sysjob);
 659 
 660         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri", NULL, uri);
 661 
 662         if (!push_utf8_talloc(frame, &user, pjob->user, &size)) {
 663                 goto out;
 664         }
 665 
 666         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
 667                      NULL, user);
 668 
 669        /*
 670         * Do the request and get back a response...
 671         */
 672 
 673         if ((response = cupsDoRequest(http, request, "/jobs")) != NULL) {
 674                 if (response->request.status.status_code >= IPP_OK_CONFLICT) {
 675                         DEBUG(0,("Unable to cancel job %d - %s\n", pjob->sysjob,
 676                                 ippErrorString(cupsLastError())));
 677                 } else {
 678                         ret = 0;
 679                 }
 680         } else {
 681                 DEBUG(0,("Unable to cancel job %d - %s\n", pjob->sysjob,
 682                         ippErrorString(cupsLastError())));
 683         }
 684 
 685  out:
 686         if (response)
 687                 ippDelete(response);
 688 
 689         if (language)
 690                 cupsLangFree(language);
 691 
 692         if (http)
 693                 httpClose(http);
 694 
 695         TALLOC_FREE(frame);
 696         return ret;
 697 }
 698 
 699 
 700 /*
 701  * 'cups_job_pause()' - Pause a job.
 702  */
 703 
 704 static int cups_job_pause(int snum, struct printjob *pjob)
     /* [<][>][^][v][top][bottom][index][help] */
 705 {
 706         TALLOC_CTX *frame = talloc_stackframe();
 707         int             ret = 1;                /* Return value */
 708         http_t          *http = NULL;           /* HTTP connection to server */
 709         ipp_t           *request = NULL,        /* IPP Request */
 710                         *response = NULL;       /* IPP Response */
 711         cups_lang_t     *language = NULL;       /* Default language */
 712         char *user = NULL;
 713         char            uri[HTTP_MAX_URI]; /* printer-uri attribute */
 714         size_t size;
 715 
 716         DEBUG(5,("cups_job_pause(%d, %p (%d))\n", snum, pjob, pjob->sysjob));
 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 = cups_connect(frame)) == NULL) {
 729                 goto out;
 730         }
 731 
 732        /*
 733         * Build an IPP_HOLD_JOB request, which requires the following
 734         * attributes:
 735         *
 736         *    attributes-charset
 737         *    attributes-natural-language
 738         *    job-uri
 739         *    requesting-user-name
 740         */
 741 
 742         request = ippNew();
 743 
 744         request->request.op.operation_id = IPP_HOLD_JOB;
 745         request->request.op.request_id   = 1;
 746 
 747         language = cupsLangDefault();
 748 
 749         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
 750                      "attributes-charset", NULL, "utf-8");
 751 
 752         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
 753                      "attributes-natural-language", NULL, language->language);
 754 
 755         slprintf(uri, sizeof(uri) - 1, "ipp://localhost/jobs/%d", pjob->sysjob);
 756 
 757         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri", NULL, uri);
 758 
 759         if (!push_utf8_talloc(frame, &user, pjob->user, &size)) {
 760                 goto out;
 761         }
 762         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
 763                      NULL, user);
 764 
 765        /*
 766         * Do the request and get back a response...
 767         */
 768 
 769         if ((response = cupsDoRequest(http, request, "/jobs")) != NULL) {
 770                 if (response->request.status.status_code >= IPP_OK_CONFLICT) {
 771                         DEBUG(0,("Unable to hold job %d - %s\n", pjob->sysjob,
 772                                 ippErrorString(cupsLastError())));
 773                 } else {
 774                         ret = 0;
 775                 }
 776         } else {
 777                 DEBUG(0,("Unable to hold job %d - %s\n", pjob->sysjob,
 778                         ippErrorString(cupsLastError())));
 779         }
 780 
 781  out:
 782         if (response)
 783                 ippDelete(response);
 784 
 785         if (language)
 786                 cupsLangFree(language);
 787 
 788         if (http)
 789                 httpClose(http);
 790 
 791         TALLOC_FREE(frame);
 792         return ret;
 793 }
 794 
 795 
 796 /*
 797  * 'cups_job_resume()' - Resume a paused job.
 798  */
 799 
 800 static int cups_job_resume(int snum, struct printjob *pjob)
     /* [<][>][^][v][top][bottom][index][help] */
 801 {
 802         TALLOC_CTX *frame = talloc_stackframe();
 803         int             ret = 1;                /* Return value */
 804         http_t          *http = NULL;           /* HTTP connection to server */
 805         ipp_t           *request = NULL,        /* IPP Request */
 806                         *response = NULL;       /* IPP Response */
 807         cups_lang_t     *language = NULL;       /* Default language */
 808         char *user = NULL;
 809         char            uri[HTTP_MAX_URI]; /* printer-uri attribute */
 810         size_t size;
 811 
 812         DEBUG(5,("cups_job_resume(%d, %p (%d))\n", snum, pjob, pjob->sysjob));
 813 
 814        /*
 815         * Make sure we don't ask for passwords...
 816         */
 817 
 818         cupsSetPasswordCB(cups_passwd_cb);
 819 
 820        /*
 821         * Try to connect to the server...
 822         */
 823 
 824         if ((http = cups_connect(frame)) == NULL) {
 825                 goto out;
 826         }
 827 
 828        /*
 829         * Build an IPP_RELEASE_JOB request, which requires the following
 830         * attributes:
 831         *
 832         *    attributes-charset
 833         *    attributes-natural-language
 834         *    job-uri
 835         *    requesting-user-name
 836         */
 837 
 838         request = ippNew();
 839 
 840         request->request.op.operation_id = IPP_RELEASE_JOB;
 841         request->request.op.request_id   = 1;
 842 
 843         language = cupsLangDefault();
 844 
 845         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
 846                      "attributes-charset", NULL, "utf-8");
 847 
 848         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
 849                      "attributes-natural-language", NULL, language->language);
 850 
 851         slprintf(uri, sizeof(uri) - 1, "ipp://localhost/jobs/%d", pjob->sysjob);
 852 
 853         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri", NULL, uri);
 854 
 855         if (!push_utf8_talloc(frame, &user, pjob->user, &size)) {
 856                 goto out;
 857         }
 858         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
 859                      NULL, user);
 860 
 861        /*
 862         * Do the request and get back a response...
 863         */
 864 
 865         if ((response = cupsDoRequest(http, request, "/jobs")) != NULL) {
 866                 if (response->request.status.status_code >= IPP_OK_CONFLICT) {
 867                         DEBUG(0,("Unable to release job %d - %s\n", pjob->sysjob,
 868                                 ippErrorString(cupsLastError())));
 869                 } else {
 870                         ret = 0;
 871                 }
 872         } else {
 873                 DEBUG(0,("Unable to release job %d - %s\n", pjob->sysjob,
 874                         ippErrorString(cupsLastError())));
 875         }
 876 
 877  out:
 878         if (response)
 879                 ippDelete(response);
 880 
 881         if (language)
 882                 cupsLangFree(language);
 883 
 884         if (http)
 885                 httpClose(http);
 886 
 887         TALLOC_FREE(frame);
 888         return ret;
 889 }
 890 
 891 
 892 /*
 893  * 'cups_job_submit()' - Submit a job for printing.
 894  */
 895 
 896 static int cups_job_submit(int snum, struct printjob *pjob)
     /* [<][>][^][v][top][bottom][index][help] */
 897 {
 898         TALLOC_CTX *frame = talloc_stackframe();
 899         int             ret = 1;                /* Return value */
 900         http_t          *http = NULL;           /* HTTP connection to server */
 901         ipp_t           *request = NULL,        /* IPP Request */
 902                         *response = NULL;       /* IPP Response */
 903         cups_lang_t     *language = NULL;       /* Default language */
 904         char            uri[HTTP_MAX_URI]; /* printer-uri attribute */
 905         const char      *clientname = NULL;     /* hostname of client for job-originating-host attribute */
 906         char *new_jobname = NULL;
 907         int             num_options = 0;
 908         cups_option_t   *options = NULL;
 909         char *printername = NULL;
 910         char *user = NULL;
 911         char *jobname = NULL;
 912         char *cupsoptions = NULL;
 913         char *filename = NULL;
 914         size_t size;
 915         char addr[INET6_ADDRSTRLEN];
 916 
 917         DEBUG(5,("cups_job_submit(%d, %p (%d))\n", snum, pjob, pjob->sysjob));
 918 
 919        /*
 920         * Make sure we don't ask for passwords...
 921         */
 922 
 923         cupsSetPasswordCB(cups_passwd_cb);
 924 
 925        /*
 926         * Try to connect to the server...
 927         */
 928 
 929         if ((http = cups_connect(frame)) == NULL) {
 930                 goto out;
 931         }
 932 
 933        /*
 934         * Build an IPP_PRINT_JOB request, which requires the following
 935         * attributes:
 936         *
 937         *    attributes-charset
 938         *    attributes-natural-language
 939         *    printer-uri
 940         *    requesting-user-name
 941         *    [document-data]
 942         */
 943 
 944         request = ippNew();
 945 
 946         request->request.op.operation_id = IPP_PRINT_JOB;
 947         request->request.op.request_id   = 1;
 948 
 949         language = cupsLangDefault();
 950 
 951         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
 952                      "attributes-charset", NULL, "utf-8");
 953 
 954         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
 955                      "attributes-natural-language", NULL, language->language);
 956 
 957         if (!push_utf8_talloc(frame, &printername, PRINTERNAME(snum), &size)) {
 958                 goto out;
 959         }
 960         slprintf(uri, sizeof(uri) - 1, "ipp://localhost/printers/%s",
 961                  printername);
 962 
 963         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
 964                      "printer-uri", NULL, uri);
 965 
 966         if (!push_utf8_talloc(frame, &user, pjob->user, &size)) {
 967                 goto out;
 968         }
 969         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
 970                      NULL, user);
 971 
 972         clientname = client_name(get_client_fd());
 973         if (strcmp(clientname, "UNKNOWN") == 0) {
 974                 clientname = client_addr(get_client_fd(),addr,sizeof(addr));
 975         }
 976 
 977         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
 978                      "job-originating-host-name", NULL,
 979                       clientname);
 980 
 981         if (!push_utf8_talloc(frame, &jobname, pjob->jobname, &size)) {
 982                 goto out;
 983         }
 984         new_jobname = talloc_asprintf(frame,
 985                         "%s%.8u %s", PRINT_SPOOL_PREFIX,
 986                         (unsigned int)pjob->smbjob,
 987                         jobname);
 988         if (new_jobname == NULL) {
 989                 goto out;
 990         }
 991 
 992         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "job-name", NULL,
 993                      new_jobname);
 994 
 995         /*
 996          * add any options defined in smb.conf
 997          */
 998 
 999         if (!push_utf8_talloc(frame, &cupsoptions, lp_cups_options(snum), &size)) {
1000                 goto out;
1001         }
1002         num_options = 0;
1003         options     = NULL;
1004         num_options = cupsParseOptions(cupsoptions, num_options, &options);
1005 
1006         if ( num_options )
1007                 cupsEncodeOptions(request, num_options, options);
1008 
1009        /*
1010         * Do the request and get back a response...
1011         */
1012 
1013         slprintf(uri, sizeof(uri) - 1, "/printers/%s", printername);
1014 
1015         if (!push_utf8_talloc(frame, &filename, pjob->filename, &size)) {
1016                 goto out;
1017         }
1018         if ((response = cupsDoFileRequest(http, request, uri, pjob->filename)) != NULL) {
1019                 if (response->request.status.status_code >= IPP_OK_CONFLICT) {
1020                         DEBUG(0,("Unable to print file to %s - %s\n", PRINTERNAME(snum),
1021                                  ippErrorString(cupsLastError())));
1022                 } else {
1023                         ret = 0;
1024                 }
1025         } else {
1026                 DEBUG(0,("Unable to print file to `%s' - %s\n", PRINTERNAME(snum),
1027                          ippErrorString(cupsLastError())));
1028         }
1029 
1030         if ( ret == 0 )
1031                 unlink(pjob->filename);
1032         /* else print_job_end will do it for us */
1033 
1034  out:
1035         if (response)
1036                 ippDelete(response);
1037 
1038         if (language)
1039                 cupsLangFree(language);
1040 
1041         if (http)
1042                 httpClose(http);
1043 
1044         TALLOC_FREE(frame);
1045 
1046         return ret;
1047 }
1048 
1049 /*
1050  * 'cups_queue_get()' - Get all the jobs in the print queue.
1051  */
1052 
1053 static int cups_queue_get(const char *sharename,
     /* [<][>][^][v][top][bottom][index][help] */
1054                enum printing_types printing_type,
1055                char *lpq_command,
1056                print_queue_struct **q,
1057                print_status_struct *status)
1058 {
1059         TALLOC_CTX *frame = talloc_stackframe();
1060         char *printername = NULL;
1061         http_t          *http = NULL;           /* HTTP connection to server */
1062         ipp_t           *request = NULL,        /* IPP Request */
1063                         *response = NULL;       /* IPP Response */
1064         ipp_attribute_t *attr = NULL;           /* Current attribute */
1065         cups_lang_t     *language = NULL;       /* Default language */
1066         char            uri[HTTP_MAX_URI]; /* printer-uri attribute */
1067         int             qcount = 0,             /* Number of active queue entries */
1068                         qalloc = 0;             /* Number of queue entries allocated */
1069         print_queue_struct *queue = NULL,       /* Queue entries */
1070                         *temp;          /* Temporary pointer for queue */
1071         char            *user_name = NULL,      /* job-originating-user-name attribute */
1072                         *job_name = NULL;       /* job-name attribute */
1073         int             job_id;         /* job-id attribute */
1074         int             job_k_octets;   /* job-k-octets attribute */
1075         time_t          job_time;       /* time-at-creation attribute */
1076         ipp_jstate_t    job_status;     /* job-status attribute */
1077         int             job_priority;   /* job-priority attribute */
1078         size_t size;
1079         static const char *jattrs[] =   /* Requested job attributes */
1080                         {
1081                           "job-id",
1082                           "job-k-octets",
1083                           "job-name",
1084                           "job-originating-user-name",
1085                           "job-priority",
1086                           "job-state",
1087                           "time-at-creation",
1088                         };
1089         static const char *pattrs[] =   /* Requested printer attributes */
1090                         {
1091                           "printer-state",
1092                           "printer-state-message"
1093                         };
1094 
1095         *q = NULL;
1096 
1097         /* HACK ALERT!!!  The problem with support the 'printer name'
1098            option is that we key the tdb off the sharename.  So we will
1099            overload the lpq_command string to pass in the printername
1100            (which is basically what we do for non-cups printers ... using
1101            the lpq_command to get the queue listing). */
1102 
1103         if (!push_utf8_talloc(frame, &printername, lpq_command, &size)) {
1104                 goto out;
1105         }
1106         DEBUG(5,("cups_queue_get(%s, %p, %p)\n", lpq_command, q, status));
1107 
1108        /*
1109         * Make sure we don't ask for passwords...
1110         */
1111 
1112         cupsSetPasswordCB(cups_passwd_cb);
1113 
1114        /*
1115         * Try to connect to the server...
1116         */
1117 
1118         if ((http = cups_connect(frame)) == NULL) {
1119                 goto out;
1120         }
1121 
1122        /*
1123         * Generate the printer URI...
1124         */
1125 
1126         slprintf(uri, sizeof(uri) - 1, "ipp://localhost/printers/%s", printername);
1127 
1128        /*
1129         * Build an IPP_GET_JOBS request, which requires the following
1130         * attributes:
1131         *
1132         *    attributes-charset
1133         *    attributes-natural-language
1134         *    requested-attributes
1135         *    printer-uri
1136         */
1137 
1138         request = ippNew();
1139 
1140         request->request.op.operation_id = IPP_GET_JOBS;
1141         request->request.op.request_id   = 1;
1142 
1143         language = cupsLangDefault();
1144 
1145         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
1146                      "attributes-charset", NULL, "utf-8");
1147 
1148         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
1149                      "attributes-natural-language", NULL, language->language);
1150 
1151         ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
1152                       "requested-attributes",
1153                       (sizeof(jattrs) / sizeof(jattrs[0])),
1154                       NULL, jattrs);
1155 
1156         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
1157                      "printer-uri", NULL, uri);
1158 
1159        /*
1160         * Do the request and get back a response...
1161         */
1162 
1163         if ((response = cupsDoRequest(http, request, "/")) == NULL) {
1164                 DEBUG(0,("Unable to get jobs for %s - %s\n", uri,
1165                          ippErrorString(cupsLastError())));
1166                 goto out;
1167         }
1168 
1169         if (response->request.status.status_code >= IPP_OK_CONFLICT) {
1170                 DEBUG(0,("Unable to get jobs for %s - %s\n", uri,
1171                          ippErrorString(response->request.status.status_code)));
1172                 goto out;
1173         }
1174 
1175        /*
1176         * Process the jobs...
1177         */
1178 
1179         qcount = 0;
1180         qalloc = 0;
1181         queue  = NULL;
1182 
1183         for (attr = response->attrs; attr != NULL; attr = attr->next) {
1184                /*
1185                 * Skip leading attributes until we hit a job...
1186                 */
1187 
1188                 while (attr != NULL && attr->group_tag != IPP_TAG_JOB)
1189                         attr = attr->next;
1190 
1191                 if (attr == NULL)
1192                         break;
1193 
1194                /*
1195                 * Allocate memory as needed...
1196                 */
1197                 if (qcount >= qalloc) {
1198                         qalloc += 16;
1199 
1200                         queue = SMB_REALLOC_ARRAY(queue, print_queue_struct, qalloc);
1201 
1202                         if (queue == NULL) {
1203                                 DEBUG(0,("cups_queue_get: Not enough memory!"));
1204                                 qcount = 0;
1205                                 goto out;
1206                         }
1207                 }
1208 
1209                 temp = queue + qcount;
1210                 memset(temp, 0, sizeof(print_queue_struct));
1211 
1212                /*
1213                 * Pull the needed attributes from this job...
1214                 */
1215 
1216                 job_id       = 0;
1217                 job_priority = 50;
1218                 job_status   = IPP_JOB_PENDING;
1219                 job_time     = 0;
1220                 job_k_octets = 0;
1221                 user_name    = NULL;
1222                 job_name     = NULL;
1223 
1224                 while (attr != NULL && attr->group_tag == IPP_TAG_JOB) {
1225                         if (attr->name == NULL) {
1226                                 attr = attr->next;
1227                                 break;
1228                         }
1229 
1230                         if (strcmp(attr->name, "job-id") == 0 &&
1231                             attr->value_tag == IPP_TAG_INTEGER)
1232                                 job_id = attr->values[0].integer;
1233 
1234                         if (strcmp(attr->name, "job-k-octets") == 0 &&
1235                             attr->value_tag == IPP_TAG_INTEGER)
1236                                 job_k_octets = attr->values[0].integer;
1237 
1238                         if (strcmp(attr->name, "job-priority") == 0 &&
1239                             attr->value_tag == IPP_TAG_INTEGER)
1240                                 job_priority = attr->values[0].integer;
1241 
1242                         if (strcmp(attr->name, "job-state") == 0 &&
1243                             attr->value_tag == IPP_TAG_ENUM)
1244                                 job_status = (ipp_jstate_t)(attr->values[0].integer);
1245 
1246                         if (strcmp(attr->name, "time-at-creation") == 0 &&
1247                             attr->value_tag == IPP_TAG_INTEGER)
1248                                 job_time = attr->values[0].integer;
1249 
1250                         if (strcmp(attr->name, "job-name") == 0 &&
1251                             attr->value_tag == IPP_TAG_NAME) {
1252                                 if (!pull_utf8_talloc(frame,
1253                                                 &job_name,
1254                                                 attr->values[0].string.text,
1255                                                 &size)) {
1256                                         goto out;
1257                                 }
1258                         }
1259 
1260                         if (strcmp(attr->name, "job-originating-user-name") == 0 &&
1261                             attr->value_tag == IPP_TAG_NAME) {
1262                                 if (!pull_utf8_talloc(frame,
1263                                                 &user_name,
1264                                                 attr->values[0].string.text,
1265                                                 &size)) {
1266                                         goto out;
1267                                 }
1268                         }
1269 
1270                         attr = attr->next;
1271                 }
1272 
1273                /*
1274                 * See if we have everything needed...
1275                 */
1276 
1277                 if (user_name == NULL || job_name == NULL || job_id == 0) {
1278                         if (attr == NULL)
1279                                 break;
1280                         else
1281                                 continue;
1282                 }
1283 
1284                 temp->job      = job_id;
1285                 temp->size     = job_k_octets * 1024;
1286                 temp->status   = job_status == IPP_JOB_PENDING ? LPQ_QUEUED :
1287                                  job_status == IPP_JOB_STOPPED ? LPQ_PAUSED :
1288                                  job_status == IPP_JOB_HELD ? LPQ_PAUSED :
1289                                  LPQ_PRINTING;
1290                 temp->priority = job_priority;
1291                 temp->time     = job_time;
1292                 strlcpy(temp->fs_user, user_name, sizeof(temp->fs_user));
1293                 strlcpy(temp->fs_file, job_name, sizeof(temp->fs_file));
1294 
1295                 qcount ++;
1296 
1297                 if (attr == NULL)
1298                         break;
1299         }
1300 
1301         ippDelete(response);
1302         response = NULL;
1303 
1304        /*
1305         * Build an IPP_GET_PRINTER_ATTRIBUTES request, which requires the
1306         * following attributes:
1307         *
1308         *    attributes-charset
1309         *    attributes-natural-language
1310         *    requested-attributes
1311         *    printer-uri
1312         */
1313 
1314         request = ippNew();
1315 
1316         request->request.op.operation_id = IPP_GET_PRINTER_ATTRIBUTES;
1317         request->request.op.request_id   = 1;
1318 
1319         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
1320                      "attributes-charset", NULL, "utf-8");
1321 
1322         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
1323                      "attributes-natural-language", NULL, language->language);
1324 
1325         ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
1326                       "requested-attributes",
1327                       (sizeof(pattrs) / sizeof(pattrs[0])),
1328                       NULL, pattrs);
1329 
1330         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
1331                      "printer-uri", NULL, uri);
1332 
1333        /*
1334         * Do the request and get back a response...
1335         */
1336 
1337         if ((response = cupsDoRequest(http, request, "/")) == NULL) {
1338                 DEBUG(0,("Unable to get printer status for %s - %s\n", printername,
1339                          ippErrorString(cupsLastError())));
1340                 *q = queue;
1341                 goto out;
1342         }
1343 
1344         if (response->request.status.status_code >= IPP_OK_CONFLICT) {
1345                 DEBUG(0,("Unable to get printer status for %s - %s\n", printername,
1346                          ippErrorString(response->request.status.status_code)));
1347                 *q = queue;
1348                 goto out;
1349         }
1350 
1351        /*
1352         * Get the current printer status and convert it to the SAMBA values.
1353         */
1354 
1355         if ((attr = ippFindAttribute(response, "printer-state", IPP_TAG_ENUM)) != NULL) {
1356                 if (attr->values[0].integer == IPP_PRINTER_STOPPED)
1357                         status->status = LPSTAT_STOPPED;
1358                 else
1359                         status->status = LPSTAT_OK;
1360         }
1361 
1362         if ((attr = ippFindAttribute(response, "printer-state-message",
1363                                      IPP_TAG_TEXT)) != NULL) {
1364                 char *msg = NULL;
1365                 if (!pull_utf8_talloc(frame, &msg,
1366                                 attr->values[0].string.text,
1367                                 &size)) {
1368                         SAFE_FREE(queue);
1369                         qcount = 0;
1370                         goto out;
1371                 }
1372                 fstrcpy(status->message, msg);
1373         }
1374 
1375        /*
1376         * Return the job queue...
1377         */
1378 
1379         *q = queue;
1380 
1381  out:
1382         if (response)
1383                 ippDelete(response);
1384 
1385         if (language)
1386                 cupsLangFree(language);
1387 
1388         if (http)
1389                 httpClose(http);
1390 
1391         TALLOC_FREE(frame);
1392         return qcount;
1393 }
1394 
1395 
1396 /*
1397  * 'cups_queue_pause()' - Pause a print queue.
1398  */
1399 
1400 static int cups_queue_pause(int snum)
     /* [<][>][^][v][top][bottom][index][help] */
1401 {
1402         TALLOC_CTX *frame = talloc_stackframe();
1403         int             ret = 1;                /* Return value */
1404         http_t          *http = NULL;           /* HTTP connection to server */
1405         ipp_t           *request = NULL,        /* IPP Request */
1406                         *response = NULL;       /* IPP Response */
1407         cups_lang_t     *language = NULL;       /* Default language */
1408         char *printername = NULL;
1409         char *username = NULL;
1410         char            uri[HTTP_MAX_URI]; /* printer-uri attribute */
1411         size_t size;
1412 
1413         DEBUG(5,("cups_queue_pause(%d)\n", snum));
1414 
1415         /*
1416          * Make sure we don't ask for passwords...
1417          */
1418 
1419         cupsSetPasswordCB(cups_passwd_cb);
1420 
1421         /*
1422          * Try to connect to the server...
1423          */
1424 
1425         if ((http = cups_connect(frame)) == NULL) {
1426                 goto out;
1427         }
1428 
1429         /*
1430          * Build an IPP_PAUSE_PRINTER request, which requires the following
1431          * attributes:
1432          *
1433          *    attributes-charset
1434          *    attributes-natural-language
1435          *    printer-uri
1436          *    requesting-user-name
1437          */
1438 
1439         request = ippNew();
1440 
1441         request->request.op.operation_id = IPP_PAUSE_PRINTER;
1442         request->request.op.request_id   = 1;
1443 
1444         language = cupsLangDefault();
1445 
1446         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
1447                      "attributes-charset", NULL, "utf-8");
1448 
1449         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
1450                      "attributes-natural-language", NULL, language->language);
1451 
1452         if (!push_utf8_talloc(frame, &printername, PRINTERNAME(snum), &size)) {
1453                 goto out;
1454         }
1455         slprintf(uri, sizeof(uri) - 1, "ipp://localhost/printers/%s",
1456                  printername);
1457 
1458         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, uri);
1459 
1460         if (!push_utf8_talloc(frame, &username, current_user_info.unix_name, &size)) {
1461                 goto out;
1462         }
1463         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
1464                      NULL, username);
1465 
1466        /*
1467         * Do the request and get back a response...
1468         */
1469 
1470         if ((response = cupsDoRequest(http, request, "/admin/")) != NULL) {
1471                 if (response->request.status.status_code >= IPP_OK_CONFLICT) {
1472                         DEBUG(0,("Unable to pause printer %s - %s\n", PRINTERNAME(snum),
1473                                 ippErrorString(cupsLastError())));
1474                 } else {
1475                         ret = 0;
1476                 }
1477         } else {
1478                 DEBUG(0,("Unable to pause printer %s - %s\n", PRINTERNAME(snum),
1479                         ippErrorString(cupsLastError())));
1480         }
1481 
1482  out:
1483         if (response)
1484                 ippDelete(response);
1485 
1486         if (language)
1487                 cupsLangFree(language);
1488 
1489         if (http)
1490                 httpClose(http);
1491 
1492         TALLOC_FREE(frame);
1493         return ret;
1494 }
1495 
1496 
1497 /*
1498  * 'cups_queue_resume()' - Restart a print queue.
1499  */
1500 
1501 static int cups_queue_resume(int snum)
     /* [<][>][^][v][top][bottom][index][help] */
1502 {
1503         TALLOC_CTX *frame = talloc_stackframe();
1504         int             ret = 1;                /* Return value */
1505         http_t          *http = NULL;           /* HTTP connection to server */
1506         ipp_t           *request = NULL,        /* IPP Request */
1507                         *response = NULL;       /* IPP Response */
1508         cups_lang_t     *language = NULL;       /* Default language */
1509         char *printername = NULL;
1510         char *username = NULL;
1511         char            uri[HTTP_MAX_URI]; /* printer-uri attribute */
1512         size_t size;
1513 
1514         DEBUG(5,("cups_queue_resume(%d)\n", snum));
1515 
1516        /*
1517         * Make sure we don't ask for passwords...
1518         */
1519 
1520         cupsSetPasswordCB(cups_passwd_cb);
1521 
1522        /*
1523         * Try to connect to the server...
1524         */
1525 
1526         if ((http = cups_connect(frame)) == NULL) {
1527                 goto out;
1528         }
1529 
1530        /*
1531         * Build an IPP_RESUME_PRINTER request, which requires the following
1532         * attributes:
1533         *
1534         *    attributes-charset
1535         *    attributes-natural-language
1536         *    printer-uri
1537         *    requesting-user-name
1538         */
1539 
1540         request = ippNew();
1541 
1542         request->request.op.operation_id = IPP_RESUME_PRINTER;
1543         request->request.op.request_id   = 1;
1544 
1545         language = cupsLangDefault();
1546 
1547         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
1548                      "attributes-charset", NULL, "utf-8");
1549 
1550         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
1551                      "attributes-natural-language", NULL, language->language);
1552 
1553         if (!push_utf8_talloc(frame, &printername, PRINTERNAME(snum), &size)) {
1554                 goto out;
1555         }
1556         slprintf(uri, sizeof(uri) - 1, "ipp://localhost/printers/%s",
1557                  printername);
1558 
1559         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, uri);
1560 
1561         if (!push_utf8_talloc(frame, &username, current_user_info.unix_name, &size)) {
1562                 goto out;
1563         }
1564         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
1565                      NULL, username);
1566 
1567        /*
1568         * Do the request and get back a response...
1569         */
1570 
1571         if ((response = cupsDoRequest(http, request, "/admin/")) != NULL) {
1572                 if (response->request.status.status_code >= IPP_OK_CONFLICT) {
1573                         DEBUG(0,("Unable to resume printer %s - %s\n", PRINTERNAME(snum),
1574                                 ippErrorString(cupsLastError())));
1575                 } else {
1576                         ret = 0;
1577                 }
1578         } else {
1579                 DEBUG(0,("Unable to resume printer %s - %s\n", PRINTERNAME(snum),
1580                         ippErrorString(cupsLastError())));
1581         }
1582 
1583  out:
1584         if (response)
1585                 ippDelete(response);
1586 
1587         if (language)
1588                 cupsLangFree(language);
1589 
1590         if (http)
1591                 httpClose(http);
1592 
1593         TALLOC_FREE(frame);
1594         return ret;
1595 }
1596 
1597 /*******************************************************************
1598  * CUPS printing interface definitions...
1599  ******************************************************************/
1600 
1601 struct printif  cups_printif =
1602 {
1603         PRINT_CUPS,
1604         cups_queue_get,
1605         cups_queue_pause,
1606         cups_queue_resume,
1607         cups_job_delete,
1608         cups_job_pause,
1609         cups_job_resume,
1610         cups_job_submit,
1611 };
1612 
1613 bool cups_pull_comment_location(NT_PRINTER_INFO_LEVEL_2 *printer)
     /* [<][>][^][v][top][bottom][index][help] */
1614 {
1615         TALLOC_CTX *frame = talloc_stackframe();
1616         http_t          *http = NULL;           /* HTTP connection to server */
1617         ipp_t           *request = NULL,        /* IPP Request */
1618                         *response = NULL;       /* IPP Response */
1619         ipp_attribute_t *attr;          /* Current attribute */
1620         cups_lang_t     *language = NULL;       /* Default language */
1621         char            uri[HTTP_MAX_URI];
1622         char *server = NULL;
1623         char *sharename = NULL;
1624         char *name = NULL;
1625         static const char *requested[] =/* Requested attributes */
1626                         {
1627                           "printer-name",
1628                           "printer-info",
1629                           "printer-location"
1630                         };
1631         bool ret = False;
1632         size_t size;
1633 
1634         DEBUG(5, ("pulling %s location\n", printer->sharename));
1635 
1636         /*
1637          * Make sure we don't ask for passwords...
1638          */
1639 
1640         cupsSetPasswordCB(cups_passwd_cb);
1641 
1642         /*
1643          * Try to connect to the server...
1644          */
1645 
1646         if ((http = cups_connect(frame)) == NULL) {
1647                 goto out;
1648         }
1649 
1650         request = ippNew();
1651 
1652         request->request.op.operation_id = IPP_GET_PRINTER_ATTRIBUTES;
1653         request->request.op.request_id   = 1;
1654 
1655         language = cupsLangDefault();
1656 
1657         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
1658                      "attributes-charset", NULL, "utf-8");
1659 
1660         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
1661                      "attributes-natural-language", NULL, language->language);
1662 
1663         if (lp_cups_server() != NULL && strlen(lp_cups_server()) > 0) {
1664                 if (!push_utf8_talloc(frame, &server, lp_cups_server(), &size)) {
1665                         goto out;
1666                 }
1667         } else {
1668                 server = talloc_strdup(frame,cupsServer());
1669         }
1670         if (server) {
1671                 goto out;
1672         }
1673         if (!push_utf8_talloc(frame, &sharename, printer->sharename, &size)) {
1674                 goto out;
1675         }
1676         slprintf(uri, sizeof(uri) - 1, "ipp://%s/printers/%s",
1677                  server, sharename);
1678 
1679         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
1680                      "printer-uri", NULL, uri);
1681 
1682         ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
1683                       "requested-attributes",
1684                       (sizeof(requested) / sizeof(requested[0])),
1685                       NULL, requested);
1686 
1687         /*
1688          * Do the request and get back a response...
1689          */
1690 
1691         if ((response = cupsDoRequest(http, request, "/")) == NULL) {
1692                 DEBUG(0,("Unable to get printer attributes - %s\n",
1693                          ippErrorString(cupsLastError())));
1694                 goto out;
1695         }
1696 
1697         for (attr = response->attrs; attr != NULL;) {
1698                 /*
1699                  * Skip leading attributes until we hit a printer...
1700                  */
1701 
1702                 while (attr != NULL && attr->group_tag != IPP_TAG_PRINTER)
1703                         attr = attr->next;
1704 
1705                 if (attr == NULL)
1706                         break;
1707 
1708                 /*
1709                  * Pull the needed attributes from this printer...
1710                  */
1711 
1712                 while ( attr && (attr->group_tag == IPP_TAG_PRINTER) ) {
1713                         if (strcmp(attr->name, "printer-name") == 0 &&
1714                             attr->value_tag == IPP_TAG_NAME) {
1715                                 if (!pull_utf8_talloc(frame,
1716                                                 &name,
1717                                                 attr->values[0].string.text,
1718                                                 &size)) {
1719                                         goto out;
1720                                 }
1721                         }
1722 
1723                         /* Grab the comment if we don't have one */
1724                         if ( (strcmp(attr->name, "printer-info") == 0)
1725                              && (attr->value_tag == IPP_TAG_TEXT)
1726                              && !strlen(printer->comment) )
1727                         {
1728                                 char *comment = NULL;
1729                                 if (!pull_utf8_talloc(frame,
1730                                                 &comment,
1731                                                 attr->values[0].string.text,
1732                                                 &size)) {
1733                                         goto out;
1734                                 }
1735                                 DEBUG(5,("cups_pull_comment_location: Using cups comment: %s\n",
1736                                          comment));
1737                                 strlcpy(printer->comment,
1738                                         comment,
1739                                         sizeof(printer->comment));
1740                         }
1741 
1742                         /* Grab the location if we don't have one */
1743                         if ( (strcmp(attr->name, "printer-location") == 0)
1744                              && (attr->value_tag == IPP_TAG_TEXT)
1745                              && !strlen(printer->location) )
1746                         {
1747                                 char *location = NULL;
1748                                 if (!pull_utf8_talloc(frame,
1749                                                 &location,
1750                                                 attr->values[0].string.text,
1751                                                 &size)) {
1752                                         goto out;
1753                                 }
1754                                 DEBUG(5,("cups_pull_comment_location: Using cups location: %s\n",
1755                                          location));
1756                                 strlcpy(printer->location,
1757                                         location,
1758                                         sizeof(printer->location));
1759                         }
1760 
1761                         attr = attr->next;
1762                 }
1763 
1764                 /*
1765                  * We have everything needed...
1766                  */
1767 
1768                 if (name != NULL)
1769                         break;
1770         }
1771 
1772         ret = True;
1773 
1774  out:
1775         if (response)
1776                 ippDelete(response);
1777 
1778         if (request) {
1779                 ippDelete(request);
1780         }
1781 
1782         if (language)
1783                 cupsLangFree(language);
1784 
1785         if (http)
1786                 httpClose(http);
1787 
1788         TALLOC_FREE(frame);
1789         return ret;
1790 }
1791 
1792 #else
1793  /* this keeps fussy compilers happy */
1794  void print_cups_dummy(void);
1795  void print_cups_dummy(void) {}
     /* [<][>][^][v][top][bottom][index][help] */
1796 #endif /* HAVE_CUPS */

/* [<][>][^][v][top][bottom][index][help] */