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