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