~ubuntu-branches/ubuntu/utopic/cups/utopic

« back to all changes in this revision

Viewing changes to backend/ipp.c

  • Committer: Package Import Robot
  • Author(s): Didier Raboud, Till Kamppeter, Steve Langasek, Didier Raboud
  • Date: 2014-01-03 18:42:39 UTC
  • mfrom: (1.3.2)
  • mto: This revision was merged to the branch mainline in revision 142.
  • Revision ID: package-import@ubuntu.com-20140103184239-juzq32ckr7ra49b3
* New 1.7.0 upstream release

[ Till Kamppeter ]
* Refresh most patches with quilt
* Removed usb-backend-do-not-crash-if-usb-disabled-in-bios and
  cupsd-no-crash-on-avahi-threaded-poll-shutdown patches as they got
  applied upstream
* Removed drop-arch-specifics-from-doc patch as it is not needed
  anymore
* Updated drop_unnecessary_dependencies, manpage-hyphen-minus,
  manpage-translations and ppd-poll-with-client-conf patches manually
  to apply to the new CUPS version
* Added error counting exception from
  usb-backend-do-not-crash-if-usb-disabled-in-bios to
  tests-ignore-warnings
* Install the newly added ippfind utility and its manpage in
  cups-client
* Added pwg.h to libcups2-dev package
* Call dh_auto_clean only if the file Makedefs is present, to avoid a
  FTBFS
* Added color management extensions from Joe Simon's GSoC 2013
  project.
* Patch cups-files.conf to activate CUPS daemon syncing of files when
  closing, so that config files (like printers.conf) do not
  mysteriously disappear (LP: #1157972)
* In the AppArmor profile, allow execution of programs in
  /etc/cups/interfaces/, needed to make CUPS working with queues based
  on System V interface scripts, especially PPD-less queues
  auto-generated by cups-browsed from cups-filters 1.0.41 on.
* Silenced AppArmor noise from udev.conf in syslog (LP: #1229766)

[ Steve Langasek ]
* Add cups-filters (>= 1.0.42) as alternative to foomatic-filters
  (which is deprecated) in package relationships

[ Didier Raboud ]
* Remove Roger Leigh from uploaders on his request with thanks for his
  past work!
* Switch avahi LSB Should-Start dependency to be avahi-daemon; also
  bump package relationship to >= 0.6.31-3~ (Closes: #731608)
* Refresh the manpage translation files
* Move the USB backend quirk rules file to cups-server-common
* Add 38 new 1.7.0 libcups2 symbols
* Mark one C++ libcupsppdc1 symbol as optional as it isn't exported in
  1.7.0 anymore
* Import Fedora patches:
  - to avoid sign-extending CRCs in gz decompression
  - to build with full read-only relocations
  - to fix job history logging (upstream patch)
  - to set the internal default for SyncOnClose to Yes, instead of
    only configuring it to Yes
  - to fix a stringpool corruption issue
  - to prevent USB timeouts causing incorrect print output
* Import Fedora patch updates:
  - to dont-use-dbus-from-two-threads patch so it removes a call to
    avahi_threaded_poll_stop()
  - to avoid_stale_lockfile_in_dbus_notifier patch to call _exit when
    handling SIGTERM
* Move manpage-translations patch at the very end of the patch series
  to have it include all our patches

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
 
 * "$Id: ipp.c 11221 2013-08-06 16:16:01Z msweet $"
3
 
 *
4
 
 *   IPP backend for CUPS.
5
 
 *
6
 
 *   Copyright 2007-2013 by Apple Inc.
7
 
 *   Copyright 1997-2007 by Easy Software Products, all rights reserved.
8
 
 *
9
 
 *   These coded instructions, statements, and computer programs are the
10
 
 *   property of Apple Inc. and are protected by Federal copyright
11
 
 *   law.  Distribution and use rights are outlined in the file "LICENSE.txt"
12
 
 *   "LICENSE" which should have been included with this file.  If this
13
 
 *   file is missing or damaged, see the license at "http://www.cups.org/".
14
 
 *
15
 
 *   This file is subject to the Apple OS-Developed Software exception.
16
 
 *
17
 
 * Contents:
18
 
 *
19
 
 *   main()                 - Send a file to the printer or server.
20
 
 *   cancel_job()           - Cancel a print job.
21
 
 *   check_printer_state()  - Check the printer state.
22
 
 *   compress_files()       - Compress print files.
23
 
 *   monitor_printer()      - Monitor the printer state.
24
 
 *   new_request()          - Create a new print creation or validation request.
25
 
 *   password_cb()          - Disable the password prompt for
26
 
 *                            cupsDoFileRequest().
27
 
 *   report_attr()          - Report an IPP attribute value.
28
 
 *   report_printer_state() - Report the printer state.
29
 
 *   run_as_user()          - Run the IPP backend as the printing user.
30
 
 *   timeout_cb()           - Handle HTTP timeouts.
31
 
 *   sigterm_handler()      - Handle 'terminate' signals that stop the backend.
 
2
 * "$Id: ipp.c 11353 2013-10-23 19:53:08Z msweet $"
 
3
 *
 
4
 * IPP backend for CUPS.
 
5
 *
 
6
 * Copyright 2007-2013 by Apple Inc.
 
7
 * Copyright 1997-2007 by Easy Software Products, all rights reserved.
 
8
 *
 
9
 * These coded instructions, statements, and computer programs are the
 
10
 * property of Apple Inc. and are protected by Federal copyright
 
11
 * law.  Distribution and use rights are outlined in the file "LICENSE.txt"
 
12
 * "LICENSE" which should have been included with this file.  If this
 
13
 * file is missing or damaged, see the license at "http://www.cups.org/".
 
14
 *
 
15
 * This file is subject to the Apple OS-Developed Software exception.
32
16
 */
33
17
 
34
18
/*
55
39
 
56
40
 
57
41
/*
 
42
 * Bits for job-state-reasons we care about...
 
43
 */
 
44
 
 
45
#define _CUPS_JSR_ACCOUNT_AUTHORIZATION_FAILED  0x01
 
46
#define _CUPS_JSR_ACCOUNT_CLOSED                0x02
 
47
#define _CUPS_JSR_ACCOUNT_INFO_NEEDED           0x04
 
48
#define _CUPS_JSR_ACCOUNT_LIMIT_REACHED         0x08
 
49
#define _CUPS_JSR_JOB_PASSWORD_WAIT             0x10
 
50
#define _CUPS_JSR_JOB_RELEASE_WAIT              0x20
 
51
 
 
52
 
 
53
/*
58
54
 * Types...
59
55
 */
60
56
 
67
63
  int                   port,           /* Port number */
68
64
                        version,        /* IPP version */
69
65
                        job_id,         /* Job ID for submitted job */
 
66
                        job_reasons,    /* Job state reasons bits */
70
67
                        get_job_attrs;  /* Support Get-Job-Attributes? */
71
68
  const char            *job_name;      /* Job name for submitted job */
72
69
  http_encryption_t     encryption;     /* Use encryption? */
102
99
                                        /* Password for device URI */
103
100
static const char * const pattrs[] =    /* Printer attributes we want */
104
101
{
 
102
#ifdef HAVE_LIBZ
 
103
  "compression-supported",
 
104
#endif /* HAVE_LIBZ */
105
105
  "copies-supported",
106
106
  "cups-version",
107
107
  "document-format-supported",
115
115
  "media-col-supported",
116
116
  "multiple-document-handling-supported",
117
117
  "operations-supported",
 
118
  "print-color-mode-supported",
118
119
  "printer-alert",
119
120
  "printer-alert-description",
120
121
  "printer-is-accepting-jobs",
153
154
static ipp_pstate_t     check_printer_state(http_t *http, const char *uri,
154
155
                                            const char *resource,
155
156
                                            const char *user, int version);
156
 
#ifdef HAVE_LIBZ
157
 
static void             compress_files(int num_files, char **files);
158
 
#endif /* HAVE_LIBZ */
159
157
static void             *monitor_printer(_cups_monitor_t *monitor);
160
158
static ipp_t            *new_request(ipp_op_t op, int version, const char *uri,
161
159
                                     const char *user, const char *title,
162
160
                                     int num_options, cups_option_t *options,
163
161
                                     const char *compression, int copies,
164
162
                                     const char *format, _ppd_cache_t *pc,
 
163
                                     ppd_file_t *ppd,
165
164
                                     ipp_attribute_t *media_col_sup,
166
 
                                     ipp_attribute_t *doc_handling_sup);
 
165
                                     ipp_attribute_t *doc_handling_sup,
 
166
                                     int print_color_mode);
167
167
static const char       *password_cb(const char *prompt, http_t *http,
168
168
                                     const char *method, const char *resource,
169
169
                                     int *user_data);
 
170
static const char       *quote_string(const char *s, char *q, size_t qsize);
170
171
static void             report_attr(ipp_attribute_t *attr);
171
172
static void             report_printer_state(ipp_t *ipp);
172
173
#if defined(HAVE_GSSAPI) && defined(HAVE_XPC)
230
231
                prev_delay;             /* Previous delay */
231
232
  const char    *compression;           /* Compression mode */
232
233
  int           waitjob,                /* Wait for job complete? */
 
234
                waitjob_tries = 0,      /* Number of times we've waited */
233
235
                waitprinter;            /* Wait for printer ready? */
234
236
  _cups_monitor_t monitor;              /* Monitoring data */
235
237
  ipp_attribute_t *job_id_attr;         /* job-id attribute */
236
238
  int           job_id;                 /* job-id value */
237
239
  ipp_attribute_t *job_sheets;          /* job-media-sheets-completed */
238
240
  ipp_attribute_t *job_state;           /* job-state */
 
241
#ifdef HAVE_LIBZ
 
242
  ipp_attribute_t *compression_sup;     /* compression-supported */
 
243
#endif /* HAVE_LIBZ */
239
244
  ipp_attribute_t *copies_sup;          /* copies-supported */
240
245
  ipp_attribute_t *cups_version;        /* cups-version */
241
246
  ipp_attribute_t *format_sup;          /* document-format-supported */
 
247
  ipp_attribute_t *job_auth;            /* job-authorization-uri */
242
248
  ipp_attribute_t *media_col_sup;       /* media-col-supported */
243
249
  ipp_attribute_t *operations_sup;      /* operations-supported */
244
250
  ipp_attribute_t *doc_handling_sup;    /* multiple-document-handling-supported */
247
253
  int           create_job = 0,         /* Does printer support Create-Job? */
248
254
                get_job_attrs = 0,      /* Does printer support Get-Job-Attributes? */
249
255
                send_document = 0,      /* Does printer support Send-Document? */
250
 
                validate_job = 0;       /* Does printer support Validate-Job? */
 
256
                validate_job = 0,       /* Does printer support Validate-Job? */
 
257
                print_color_mode = 0;   /* Does printer support print-color-mode? */
251
258
  int           copies,                 /* Number of copies for job */
252
259
                copies_remaining;       /* Number of copies remaining */
253
260
  const char    *content_type,          /* CONTENT_TYPE environment variable */
260
267
  struct sigaction action;              /* Actions for POSIX signals */
261
268
#endif /* HAVE_SIGACTION && !HAVE_SIGSET */
262
269
  int           version;                /* IPP version */
263
 
  ppd_file_t    *ppd;                   /* PPD file */
264
 
  _ppd_cache_t  *pc;                    /* PPD cache and mapping data */
 
270
  ppd_file_t    *ppd = NULL;            /* PPD file */
 
271
  _ppd_cache_t  *pc = NULL;             /* PPD cache and mapping data */
265
272
  fd_set        input;                  /* Input set for select() */
266
273
 
267
274
 
334
341
  if ((auth_info_required = getenv("AUTH_INFO_REQUIRED")) == NULL)
335
342
    auth_info_required = "none";
336
343
 
337
 
  state_reasons = _cupsArrayNewStrings(getenv("PRINTER_STATE_REASONS"));
 
344
  state_reasons = _cupsArrayNewStrings(getenv("PRINTER_STATE_REASONS"), ',');
338
345
 
339
346
#ifdef HAVE_GSSAPI
340
347
 /*
342
349
  * that way.
343
350
  */
344
351
 
345
 
  if (!getuid() && (value = getenv("AUTH_UID")) != NULL)
 
352
  if (!getuid() && (value = getenv("AUTH_UID")) != NULL &&
 
353
      !getenv("AUTH_PASSWORD"))
346
354
  {
347
355
    uid_t       uid = (uid_t)atoi(value);
348
356
                                        /* User ID */
546
554
        if (!_cups_strcasecmp(value, "true") || !_cups_strcasecmp(value, "yes") ||
547
555
            !_cups_strcasecmp(value, "on") || !_cups_strcasecmp(value, "gzip"))
548
556
          compression = "gzip";
 
557
        else if (!_cups_strcasecmp(value, "deflate"))
 
558
          compression = "deflate";
 
559
        else if (!_cups_strcasecmp(value, "false") ||
 
560
                 !_cups_strcasecmp(value, "no") ||
 
561
                 !_cups_strcasecmp(value, "off") ||
 
562
                 !_cups_strcasecmp(value, "none"))
 
563
          compression = "none";
549
564
      }
550
565
#endif /* HAVE_LIBZ */
551
566
      else if (!_cups_strcasecmp(name, "contimeout"))
596
611
    files        = argv + 6;
597
612
    send_options = 1;
598
613
 
599
 
#ifdef HAVE_LIBZ
600
 
    if (compression)
601
 
      compress_files(num_files, files);
602
 
#endif /* HAVE_LIBZ */
603
 
 
604
614
    fprintf(stderr, "DEBUG: %d files to send in job...\n", num_files);
605
615
  }
606
616
 
613
623
  if (username[0])
614
624
  {
615
625
   /*
616
 
    * Use authenticaion information in the device URI...
 
626
    * Use authentication information in the device URI...
617
627
    */
618
628
 
619
629
    if ((password = strchr(username, ':')) != NULL)
665
675
      return (CUPS_BACKEND_OK);
666
676
  }
667
677
 
668
 
  http = _httpCreate(hostname, port, addrlist, cupsEncryption(), AF_UNSPEC);
 
678
  http = httpConnect2(hostname, port, addrlist, AF_UNSPEC, cupsEncryption(), 1,
 
679
                      0, NULL);
669
680
  httpSetTimeout(http, 30.0, timeout_cb, NULL);
670
681
 
671
682
 /*
803
814
 
804
815
  fprintf(stderr, "DEBUG: Connected to %s:%d...\n",
805
816
          httpAddrString(http->hostaddr, addrname, sizeof(addrname)),
806
 
          _httpAddrPort(http->hostaddr));
 
817
          httpAddrPort(http->hostaddr));
807
818
 
808
819
 /*
809
820
  * Build a URI for the printer and fill the standard IPP attributes for
819
830
  * copies...
820
831
  */
821
832
 
 
833
#ifdef HAVE_LIBZ
 
834
  compression_sup  = NULL;
 
835
#endif /* HAVE_LIBZ */
822
836
  copies_sup       = NULL;
823
837
  cups_version     = NULL;
824
838
  format_sup       = NULL;
904
918
 
905
919
        if (version >= 20)
906
920
        {
907
 
          _cupsLangPrintFilter(stderr, "INFO",
908
 
                               _("The printer does not support IPP/%d.%d, trying "
909
 
                                 "IPP/%s."), version / 10, version % 10, "1.1");
 
921
          _cupsLangPrintFilter(stderr, "INFO", _("Preparing to print."));
 
922
          fprintf(stderr,
 
923
                  "DEBUG: The printer does not support IPP/%d.%d, trying "
 
924
                  "IPP/1.1.\n", version / 10, version % 10);
910
925
          version = 11;
911
926
        }
912
927
        else
913
928
        {
914
 
          _cupsLangPrintFilter(stderr, "INFO",
915
 
                               _("The printer does not support IPP/%d.%d, trying "
916
 
                                 "IPP/%s."), version / 10, version % 10, "1.0");
 
929
          _cupsLangPrintFilter(stderr, "INFO", _("Preparing to print."));
 
930
          fprintf(stderr,
 
931
                  "DEBUG: The printer does not support IPP/%d.%d, trying "
 
932
                  "IPP/1.0.\n", version / 10, version % 10);
917
933
          version = 10;
918
934
        }
919
935
 
922
938
      else if (ipp_status == IPP_NOT_FOUND)
923
939
      {
924
940
        _cupsLangPrintFilter(stderr, "ERROR",
925
 
                             _("The printer URI is incorrect or no longer "
926
 
                               "exists."));
 
941
                             _("The printer configuration is incorrect or the "
 
942
                               "printer no longer exists."));
927
943
 
928
944
        ippDelete(supported);
929
945
 
1017
1033
    * Check for supported attributes...
1018
1034
    */
1019
1035
 
 
1036
#ifdef HAVE_LIBZ
 
1037
    if ((compression_sup = ippFindAttribute(supported, "compression-supported",
 
1038
                                            IPP_TAG_KEYWORD)) != NULL)
 
1039
    {
 
1040
     /*
 
1041
      * Check whether the requested compression is supported and/or default to
 
1042
      * compression if supported...
 
1043
      */
 
1044
 
 
1045
      if (compression && !ippContainsString(compression_sup, compression))
 
1046
      {
 
1047
        fprintf(stderr, "DEBUG: Printer does not support the requested "
 
1048
                        "compression value \"%s\".\n", compression);
 
1049
        compression = NULL;
 
1050
      }
 
1051
      else if (!compression)
 
1052
      {
 
1053
        if (ippContainsString(compression_sup, "gzip"))
 
1054
          compression = "gzip";
 
1055
        else if (ippContainsString(compression_sup, "deflate"))
 
1056
          compression = "deflate";
 
1057
 
 
1058
        if (compression)
 
1059
          fprintf(stderr, "DEBUG: Automatically using \"%s\" compression.\n",
 
1060
                  compression);
 
1061
      }
 
1062
    }
 
1063
#endif /* HAVE_LIBZ */
 
1064
 
1020
1065
    if ((copies_sup = ippFindAttribute(supported, "copies-supported",
1021
1066
                                       IPP_TAG_RANGE)) != NULL)
1022
1067
    {
1055
1100
                media_col_sup->values[i].string.text);
1056
1101
    }
1057
1102
 
 
1103
    print_color_mode = ippFindAttribute(supported,
 
1104
                                        "print-color-mode-supported",
 
1105
                                        IPP_TAG_KEYWORD) != NULL;
 
1106
 
1058
1107
    if ((operations_sup = ippFindAttribute(supported, "operations-supported",
1059
1108
                                           IPP_TAG_ENUM)) != NULL)
1060
1109
    {
1195
1244
  */
1196
1245
 
1197
1246
  options = NULL;
1198
 
  pc      = NULL;
1199
1247
 
1200
1248
  if (send_options)
1201
1249
  {
1210
1258
      ppd = ppdOpenFile(getenv("PPD"));
1211
1259
      pc  = _ppdCacheCreateWithPPD(ppd);
1212
1260
 
1213
 
      ppdClose(ppd);
 
1261
      ppdMarkDefaults(ppd);
 
1262
      cupsMarkOptions(ppd, num_options, options);
1214
1263
    }
1215
1264
  }
1216
1265
  else
1334
1383
  {
1335
1384
    request = new_request(IPP_VALIDATE_JOB, version, uri, argv[2],
1336
1385
                          monitor.job_name, num_options, options, compression,
1337
 
                          copies_sup ? copies : 1, document_format, pc,
1338
 
                          media_col_sup, doc_handling_sup);
 
1386
                          copies_sup ? copies : 1, document_format, pc, ppd,
 
1387
                          media_col_sup, doc_handling_sup, print_color_mode);
1339
1388
 
1340
 
    ippDelete(cupsDoRequest(http, request, resource));
 
1389
    response = cupsDoRequest(http, request, resource);
1341
1390
 
1342
1391
    ipp_status = cupsLastError();
1343
1392
 
1344
1393
    fprintf(stderr, "DEBUG: Validate-Job: %s (%s)\n",
1345
1394
            ippErrorString(ipp_status), cupsLastErrorString());
1346
1395
 
 
1396
    if ((job_auth = ippFindAttribute(response, "job-authorization-uri",
 
1397
                                     IPP_TAG_URI)) != NULL)
 
1398
      num_options = cupsAddOption("job-authorization-uri",
 
1399
                                  ippGetString(job_auth, 0, NULL), num_options,
 
1400
                                  &options);
 
1401
 
 
1402
    ippDelete(response);
 
1403
 
1347
1404
    if (job_canceled)
1348
1405
      break;
1349
1406
 
1350
 
    if (ipp_status == IPP_SERVICE_UNAVAILABLE || ipp_status == IPP_PRINTER_BUSY)
 
1407
    if (ipp_status == IPP_STATUS_ERROR_SERVICE_UNAVAILABLE ||
 
1408
        ipp_status == IPP_STATUS_ERROR_BUSY)
1351
1409
    {
1352
1410
      _cupsLangPrintFilter(stderr, "INFO", _("The printer is in use."));
1353
1411
      sleep(10);
1354
1412
    }
1355
 
    else if (ipp_status == IPP_DOCUMENT_FORMAT)
 
1413
    else if (ipp_status == IPP_STATUS_ERROR_DOCUMENT_FORMAT_NOT_SUPPORTED ||
 
1414
             ipp_status == IPP_STATUS_ERROR_CUPS_ACCOUNT_INFO_NEEDED ||
 
1415
             ipp_status == IPP_STATUS_ERROR_CUPS_ACCOUNT_CLOSED ||
 
1416
             ipp_status == IPP_STATUS_ERROR_CUPS_ACCOUNT_LIMIT_REACHED ||
 
1417
             ipp_status == IPP_STATUS_ERROR_CUPS_ACCOUNT_AUTHORIZATION_FAILED)
1356
1418
      goto cleanup;
1357
 
    else if (ipp_status == IPP_FORBIDDEN ||
1358
 
             ipp_status == IPP_AUTHENTICATION_CANCELED)
 
1419
    else if (ipp_status == IPP_STATUS_ERROR_FORBIDDEN ||
 
1420
             ipp_status == IPP_STATUS_ERROR_CUPS_AUTHENTICATION_CANCELED)
1359
1421
    {
1360
1422
      const char *www_auth = httpGetField(http, HTTP_FIELD_WWW_AUTHENTICATE);
1361
1423
                                        /* WWW-Authenticate field value */
1367
1429
 
1368
1430
      goto cleanup;
1369
1431
    }
1370
 
    else if (ipp_status == IPP_OPERATION_NOT_SUPPORTED)
 
1432
    else if (ipp_status == IPP_STATUS_ERROR_OPERATION_NOT_SUPPORTED)
1371
1433
    {
1372
1434
     /*
1373
1435
      * This is all too common...
1407
1469
                                                          IPP_PRINT_JOB,
1408
1470
                          version, uri, argv[2], monitor.job_name, num_options,
1409
1471
                          options, compression, copies_sup ? copies : 1,
1410
 
                          document_format, pc, media_col_sup, doc_handling_sup);
 
1472
                          document_format, pc, ppd, media_col_sup,
 
1473
                          doc_handling_sup, print_color_mode);
1411
1474
 
1412
1475
   /*
1413
1476
    * Do the request...
1430
1493
      http_status = cupsSendRequest(http, request, resource, length);
1431
1494
      if (http_status == HTTP_CONTINUE && request->state == IPP_DATA)
1432
1495
      {
 
1496
        if (compression && strcmp(compression, "none"))
 
1497
          httpSetField(http, HTTP_FIELD_CONTENT_ENCODING, compression);
 
1498
 
1433
1499
        if (num_files == 1)
1434
1500
        {
1435
1501
          if ((fd = open(files[0], O_RDONLY)) < 0)
1467
1533
            {
1468
1534
              fprintf(stderr, "DEBUG: Read %d bytes...\n", (int)bytes);
1469
1535
 
1470
 
              if (cupsWriteRequestData(http, buffer, bytes) != HTTP_CONTINUE)
 
1536
              if ((http_status = cupsWriteRequestData(http, buffer, bytes))
 
1537
                      != HTTP_CONTINUE)
1471
1538
                break;
1472
1539
            }
1473
1540
            else if (bytes == 0 || (errno != EINTR && errno != EAGAIN))
1475
1542
          }
1476
1543
        }
1477
1544
 
 
1545
        if (http_status == HTTP_ERROR)
 
1546
          fprintf(stderr, "DEBUG: Error writing document data for "
 
1547
                          "Print-Job: %s\n", strerror(httpError(http)));
 
1548
 
1478
1549
        if (num_files == 1)
1479
1550
          close(fd);
1480
1551
      }
1496
1567
      if (job_canceled)
1497
1568
        break;
1498
1569
 
1499
 
      if (ipp_status == IPP_SERVICE_UNAVAILABLE ||
1500
 
          ipp_status == IPP_NOT_POSSIBLE ||
1501
 
          ipp_status == IPP_PRINTER_BUSY)
 
1570
      if (ipp_status == IPP_STATUS_ERROR_SERVICE_UNAVAILABLE ||
 
1571
          ipp_status == IPP_STATUS_ERROR_NOT_POSSIBLE ||
 
1572
          ipp_status == IPP_STATUS_ERROR_BUSY)
1502
1573
      {
1503
1574
        _cupsLangPrintFilter(stderr, "INFO", _("The printer is in use."));
1504
1575
        sleep(10);
1513
1584
          goto cleanup;
1514
1585
        }
1515
1586
      }
1516
 
      else if (ipp_status == IPP_ERROR_JOB_CANCELED ||
1517
 
               ipp_status == IPP_NOT_AUTHORIZED)
 
1587
      else if (ipp_status == IPP_STATUS_ERROR_JOB_CANCELED ||
 
1588
               ipp_status == IPP_STATUS_ERROR_NOT_AUTHORIZED ||
 
1589
               ipp_status == IPP_STATUS_ERROR_ATTRIBUTES_OR_VALUES ||
 
1590
               ipp_status == IPP_STATUS_ERROR_CUPS_ACCOUNT_INFO_NEEDED ||
 
1591
               ipp_status == IPP_STATUS_ERROR_CUPS_ACCOUNT_CLOSED ||
 
1592
               ipp_status == IPP_STATUS_ERROR_CUPS_ACCOUNT_LIMIT_REACHED ||
 
1593
               ipp_status == IPP_STATUS_ERROR_CUPS_ACCOUNT_AUTHORIZATION_FAILED)
1518
1594
        goto cleanup;
1519
1595
      else
1520
1596
      {
1523
1599
        */
1524
1600
 
1525
1601
        _cupsLangPrintFilter(stderr, "ERROR",
1526
 
                             _("Print file was not accepted."));
 
1602
                             _("Print job was not accepted."));
1527
1603
 
1528
 
        if (ipp_status == IPP_FORBIDDEN ||
1529
 
            ipp_status == IPP_AUTHENTICATION_CANCELED)
 
1604
        if (ipp_status == IPP_STATUS_ERROR_FORBIDDEN ||
 
1605
            ipp_status == IPP_STATUS_ERROR_CUPS_AUTHENTICATION_CANCELED)
1530
1606
        {
1531
1607
          const char *www_auth = httpGetField(http, HTTP_FIELD_WWW_AUTHENTICATE);
1532
1608
                                        /* WWW-Authenticate field value */
1561
1637
    else if ((job_id_attr = ippFindAttribute(response, "job-id",
1562
1638
                                             IPP_TAG_INTEGER)) == NULL)
1563
1639
    {
1564
 
      _cupsLangPrintFilter(stderr, "INFO",
1565
 
                           _("Print file accepted - job ID unknown."));
 
1640
      fputs("DEBUG: Print job accepted - job ID unknown.\n", stderr);
1566
1641
      update_reasons(NULL, "+cups-ipp-conformance-failure-report,"
1567
1642
                           "cups-ipp-missing-job-id");
1568
1643
      job_id = 0;
1571
1646
    {
1572
1647
      password_tries = 0;
1573
1648
      monitor.job_id = job_id = job_id_attr->values[0].integer;
1574
 
      _cupsLangPrintFilter(stderr, "INFO",
1575
 
                           _("Print file accepted - job ID %d."), job_id);
 
1649
      fprintf(stderr, "DEBUG: Print job accepted - job ID %d.\n", job_id);
1576
1650
    }
1577
1651
 
1578
 
    fprintf(stderr, "DEBUG: job-id=%d\n", job_id);
1579
1652
    ippDelete(response);
1580
1653
 
1581
1654
    if (job_canceled)
1627
1700
        http_status = cupsSendRequest(http, request, resource, 0);
1628
1701
        if (http_status == HTTP_CONTINUE && request->state == IPP_DATA)
1629
1702
        {
 
1703
          if (compression && strcmp(compression, "none"))
 
1704
            httpSetField(http, HTTP_FIELD_CONTENT_ENCODING, compression);
 
1705
 
1630
1706
          if (num_files == 0)
1631
1707
          {
1632
1708
            fd          = 0;
1666
1742
            close(fd);
1667
1743
        }
1668
1744
 
 
1745
        if (http_status == HTTP_ERROR)
 
1746
          fprintf(stderr, "DEBUG: Error writing document data for "
 
1747
                          "Send-Document: %s\n", strerror(httpError(http)));
 
1748
 
1669
1749
        ippDelete(cupsGetResponse(http, resource));
1670
1750
        ippDelete(request);
1671
1751
 
1716
1796
    else if (ipp_status == IPP_REQUEST_VALUE ||
1717
1797
             ipp_status == IPP_ERROR_JOB_CANCELED ||
1718
1798
             ipp_status == IPP_NOT_AUTHORIZED ||
 
1799
             ipp_status == IPP_STATUS_ERROR_CUPS_ACCOUNT_INFO_NEEDED ||
 
1800
             ipp_status == IPP_STATUS_ERROR_CUPS_ACCOUNT_CLOSED ||
 
1801
             ipp_status == IPP_STATUS_ERROR_CUPS_ACCOUNT_LIMIT_REACHED ||
 
1802
             ipp_status == IPP_STATUS_ERROR_CUPS_ACCOUNT_AUTHORIZATION_FAILED ||
1719
1803
             ipp_status == IPP_INTERNAL_ERROR)
1720
1804
    {
1721
1805
     /*
1725
1809
 
1726
1810
      goto cleanup;
1727
1811
    }
1728
 
    else if (ipp_status == IPP_UPGRADE_REQUIRED)
 
1812
    else if (ipp_status == IPP_STATUS_ERROR_CUPS_UPGRADE_REQUIRED)
1729
1813
    {
1730
1814
     /*
1731
1815
      * Server is configured incorrectly; the policy for Create-Job and
1739
1823
      fputs("DEBUG: The policy for Create-Job and Send-Document must have the "
1740
1824
            "same authentication and encryption requirements.\n", stderr);
1741
1825
 
1742
 
      ipp_status = IPP_INTERNAL_ERROR;
 
1826
      ipp_status = IPP_STATUS_ERROR_INTERNAL;
1743
1827
 
1744
1828
      if (job_id > 0)
1745
1829
        cancel_job(http, uri, job_id, resource, argv[2], version);
1785
1869
      backendCheckSideChannel(snmp_fd, http->hostaddr);
1786
1870
 
1787
1871
     /*
 
1872
      * Check printer state...
 
1873
      */
 
1874
 
 
1875
      check_printer_state(http, uri, resource, argv[2], version);
 
1876
 
 
1877
      if (cupsLastError() <= IPP_OK_CONFLICT)
 
1878
        password_tries = 0;
 
1879
 
 
1880
     /*
1788
1881
      * Build an IPP_GET_JOB_ATTRIBUTES request...
1789
1882
      */
1790
1883
 
1842
1935
          ipp_status = IPP_OK;
1843
1936
          break;
1844
1937
        }
 
1938
        else if (ipp_status == IPP_INTERNAL_ERROR)
 
1939
        {
 
1940
          waitjob_tries ++;
 
1941
 
 
1942
          if (waitjob_tries > 4)
 
1943
          {
 
1944
            ippDelete(response);
 
1945
            ipp_status = IPP_OK;
 
1946
            break;
 
1947
          }
 
1948
        }
1845
1949
      }
1846
1950
 
1847
1951
      if (response)
1900
2004
 
1901
2005
      ippDelete(response);
1902
2006
 
1903
 
      if (cupsLastError() <= IPP_OK_CONFLICT)
1904
 
        password_tries = 0;
1905
 
 
1906
2007
     /*
1907
2008
      * Wait before polling again...
1908
2009
      */
1956
2057
 
1957
2058
  cupsFreeOptions(num_options, options);
1958
2059
  _ppdCacheDestroy(pc);
 
2060
  ppdClose(ppd);
1959
2061
 
1960
2062
  httpClose(http);
1961
2063
 
1968
2070
  if (tmpfilename[0])
1969
2071
    unlink(tmpfilename);
1970
2072
 
1971
 
#ifdef HAVE_LIBZ
1972
 
  if (compression)
1973
 
  {
1974
 
    for (i = 0; i < num_files; i ++)
1975
 
      unlink(files[i]);
1976
 
  }
1977
 
#endif /* HAVE_LIBZ */
1978
 
 
1979
2073
 /*
1980
2074
  * Return the queue status...
1981
2075
  */
1985
2079
      ipp_status <= IPP_OK_CONFLICT)
1986
2080
    fprintf(stderr, "ATTR: auth-info-required=%s\n", auth_info_required);
1987
2081
 
 
2082
  if (ipp_status == IPP_STATUS_ERROR_CUPS_ACCOUNT_INFO_NEEDED)
 
2083
    fputs("JOBSTATE: account-info-needed\n", stderr);
 
2084
  else if (ipp_status == IPP_STATUS_ERROR_CUPS_ACCOUNT_CLOSED)
 
2085
    fputs("JOBSTATE: account-closed\n", stderr);
 
2086
  else if (ipp_status == IPP_STATUS_ERROR_CUPS_ACCOUNT_LIMIT_REACHED)
 
2087
    fputs("JOBSTATE: account-limit-reached\n", stderr);
 
2088
  else if (ipp_status == IPP_STATUS_ERROR_CUPS_ACCOUNT_AUTHORIZATION_FAILED)
 
2089
    fputs("JOBSTATE: account-authorization-failed\n", stderr);
 
2090
 
1988
2091
  if (ipp_status == IPP_NOT_AUTHORIZED || ipp_status == IPP_FORBIDDEN ||
1989
2092
      ipp_status == IPP_AUTHENTICATION_CANCELED)
1990
2093
    return (CUPS_BACKEND_AUTH_REQUIRED);
 
2094
  else if (ipp_status == IPP_STATUS_ERROR_CUPS_ACCOUNT_LIMIT_REACHED ||
 
2095
           ipp_status == IPP_STATUS_ERROR_CUPS_ACCOUNT_INFO_NEEDED ||
 
2096
           ipp_status == IPP_STATUS_ERROR_CUPS_ACCOUNT_CLOSED ||
 
2097
           ipp_status == IPP_STATUS_ERROR_CUPS_ACCOUNT_AUTHORIZATION_FAILED)
 
2098
    return (CUPS_BACKEND_HOLD);
1991
2099
  else if (ipp_status == IPP_INTERNAL_ERROR)
1992
2100
    return (CUPS_BACKEND_STOP);
1993
2101
  else if (ipp_status == IPP_CONFLICT)
1994
2102
    return (CUPS_BACKEND_FAILED);
1995
2103
  else if (ipp_status == IPP_REQUEST_VALUE ||
 
2104
           ipp_status == IPP_STATUS_ERROR_ATTRIBUTES_OR_VALUES ||
1996
2105
           ipp_status == IPP_DOCUMENT_FORMAT || job_canceled < 0)
1997
2106
  {
1998
2107
    if (ipp_status == IPP_REQUEST_VALUE)
2000
2109
    else if (ipp_status == IPP_DOCUMENT_FORMAT)
2001
2110
      _cupsLangPrintFilter(stderr, "ERROR",
2002
2111
                           _("Printer cannot print supplied content."));
 
2112
    else if (ipp_status == IPP_STATUS_ERROR_ATTRIBUTES_OR_VALUES)
 
2113
      _cupsLangPrintFilter(stderr, "ERROR",
 
2114
                           _("Printer cannot print with supplied options."));
2003
2115
    else
2004
2116
      _cupsLangPrintFilter(stderr, "ERROR", _("Print job canceled at printer."));
2005
2117
 
2112
2224
}
2113
2225
 
2114
2226
 
2115
 
#ifdef HAVE_LIBZ
2116
 
/*
2117
 
 * 'compress_files()' - Compress print files.
2118
 
 */
2119
 
 
2120
 
static void
2121
 
compress_files(int  num_files,          /* I - Number of files */
2122
 
               char **files)            /* I - Files */
2123
 
{
2124
 
  int           i,                      /* Looping var */
2125
 
                fd;                     /* Temporary file descriptor */
2126
 
  ssize_t       bytes;                  /* Bytes read/written */
2127
 
  size_t        total;                  /* Total bytes read */
2128
 
  cups_file_t   *in,                    /* Input file */
2129
 
                *out;                   /* Output file */
2130
 
  struct stat   outinfo;                /* Output file information */
2131
 
  char          filename[1024],         /* Temporary filename */
2132
 
                buffer[32768];          /* Copy buffer */
2133
 
 
2134
 
 
2135
 
  fprintf(stderr, "DEBUG: Compressing %d job files...\n", num_files);
2136
 
  for (i = 0; i < num_files; i ++)
2137
 
  {
2138
 
    if ((fd = cupsTempFd(filename, sizeof(filename))) < 0)
2139
 
    {
2140
 
      _cupsLangPrintError("ERROR", _("Unable to create compressed print file"));
2141
 
      exit(CUPS_BACKEND_FAILED);
2142
 
    }
2143
 
 
2144
 
    if ((out = cupsFileOpenFd(fd, "w9")) == NULL)
2145
 
    {
2146
 
      _cupsLangPrintError("ERROR", _("Unable to open compressed print file"));
2147
 
      exit(CUPS_BACKEND_FAILED);
2148
 
    }
2149
 
 
2150
 
    if ((in = cupsFileOpen(files[i], "r")) == NULL)
2151
 
    {
2152
 
      _cupsLangPrintError("ERROR", _("Unable to open print file"));
2153
 
      cupsFileClose(out);
2154
 
      exit(CUPS_BACKEND_FAILED);
2155
 
    }
2156
 
 
2157
 
    total = 0;
2158
 
    while ((bytes = cupsFileRead(in, buffer, sizeof(buffer))) > 0)
2159
 
      if (cupsFileWrite(out, buffer, bytes) < bytes)
2160
 
      {
2161
 
        _cupsLangPrintError("ERROR",
2162
 
                            _("Unable to generate compressed print file"));
2163
 
        cupsFileClose(in);
2164
 
        cupsFileClose(out);
2165
 
        exit(CUPS_BACKEND_FAILED);
2166
 
      }
2167
 
      else
2168
 
        total += bytes;
2169
 
 
2170
 
    cupsFileClose(out);
2171
 
    cupsFileClose(in);
2172
 
 
2173
 
    files[i] = strdup(filename);
2174
 
 
2175
 
    if (!stat(filename, &outinfo))
2176
 
      fprintf(stderr,
2177
 
              "DEBUG: File %d compressed to %.1f%% of original size, "
2178
 
              CUPS_LLFMT " bytes...\n",
2179
 
              i + 1, 100.0 * outinfo.st_size / total,
2180
 
              CUPS_LLCAST outinfo.st_size);
2181
 
  }
2182
 
}
2183
 
#endif /* HAVE_LIBZ */
2184
 
 
2185
 
 
2186
2227
/*
2187
2228
 * 'monitor_printer()' - Monitor the printer state.
2188
2229
 */
2209
2250
  * Make a copy of the printer connection...
2210
2251
  */
2211
2252
 
2212
 
  http = _httpCreate(monitor->hostname, monitor->port, NULL, monitor->encryption,
2213
 
                     AF_UNSPEC);
 
2253
  http = httpConnect2(monitor->hostname, monitor->port, NULL, AF_UNSPEC,
 
2254
                      monitor->encryption, 1, 0, NULL);
2214
2255
  httpSetTimeout(http, 30.0, timeout_cb, NULL);
2215
2256
  if (username[0])
2216
2257
    cupsSetUser(username);
 
2258
 
2217
2259
  cupsSetPasswordCB2((cups_password_cb2_t)password_cb, &password_tries);
2218
2260
 
2219
2261
 /*
2222
2264
 
2223
2265
  delay = _cupsNextDelay(0, &prev_delay);
2224
2266
 
 
2267
  monitor->job_reasons = 0;
 
2268
 
2225
2269
  while (monitor->job_state < IPP_JOB_CANCELED && !job_canceled)
2226
2270
  {
2227
2271
   /*
2333
2377
        }
2334
2378
      }
2335
2379
 
 
2380
      if ((attr = ippFindAttribute(response, "job-state-reasons",
 
2381
                                   IPP_TAG_KEYWORD)) != NULL)
 
2382
      {
 
2383
        int     i, new_reasons = 0;     /* Looping var, new reasons */
 
2384
 
 
2385
        for (i = 0; i < attr->num_values; i ++)
 
2386
        {
 
2387
          if (!strcmp(attr->values[i].string.text,
 
2388
                      "account-authorization-failed"))
 
2389
            new_reasons |= _CUPS_JSR_ACCOUNT_AUTHORIZATION_FAILED;
 
2390
          else if (!strcmp(attr->values[i].string.text, "account-closed"))
 
2391
            new_reasons |= _CUPS_JSR_ACCOUNT_CLOSED;
 
2392
          else if (!strcmp(attr->values[i].string.text, "account-info-needed"))
 
2393
            new_reasons |= _CUPS_JSR_ACCOUNT_INFO_NEEDED;
 
2394
          else if (!strcmp(attr->values[i].string.text,
 
2395
                           "account-limit-reached"))
 
2396
            new_reasons |= _CUPS_JSR_ACCOUNT_LIMIT_REACHED;
 
2397
          else if (!strcmp(attr->values[i].string.text, "job-password-wait"))
 
2398
            new_reasons |= _CUPS_JSR_JOB_PASSWORD_WAIT;
 
2399
          else if (!strcmp(attr->values[i].string.text, "job-release-wait"))
 
2400
            new_reasons |= _CUPS_JSR_JOB_RELEASE_WAIT;
 
2401
        }
 
2402
 
 
2403
        if (new_reasons != monitor->job_reasons)
 
2404
        {
 
2405
          if (new_reasons & _CUPS_JSR_ACCOUNT_AUTHORIZATION_FAILED)
 
2406
            fputs("JOBSTATE: account-authorization-failed\n", stderr);
 
2407
          else if (new_reasons & _CUPS_JSR_ACCOUNT_CLOSED)
 
2408
            fputs("JOBSTATE: account-closed\n", stderr);
 
2409
          else if (new_reasons & _CUPS_JSR_ACCOUNT_INFO_NEEDED)
 
2410
            fputs("JOBSTATE: account-info-needed\n", stderr);
 
2411
          else if (new_reasons & _CUPS_JSR_ACCOUNT_LIMIT_REACHED)
 
2412
            fputs("JOBSTATE: account-limit-reached\n", stderr);
 
2413
          else if (new_reasons & _CUPS_JSR_JOB_PASSWORD_WAIT)
 
2414
            fputs("JOBSTATE: job-password-wait\n", stderr);
 
2415
          else if (new_reasons & _CUPS_JSR_JOB_RELEASE_WAIT)
 
2416
            fputs("JOBSTATE: job-release-wait\n", stderr);
 
2417
          else
 
2418
            fputs("JOBSTATE: job-printing\n", stderr);
 
2419
 
 
2420
          monitor->job_reasons = new_reasons;
 
2421
        }
 
2422
      }
 
2423
 
2336
2424
      ippDelete(response);
2337
2425
 
2338
2426
      fprintf(stderr, "DEBUG: (monitor) job-state=%s\n",
2395
2483
    int             copies,             /* I - copies value or 0 */
2396
2484
    const char      *format,            /* I - document-format value or NULL */
2397
2485
    _ppd_cache_t    *pc,                /* I - PPD cache and mapping data */
 
2486
    ppd_file_t      *ppd,               /* I - PPD file data */
2398
2487
    ipp_attribute_t *media_col_sup,     /* I - media-col-supported values */
2399
 
    ipp_attribute_t *doc_handling_sup)  /* I - multiple-document-handling-supported values */
 
2488
    ipp_attribute_t *doc_handling_sup,  /* I - multiple-document-handling-supported values */
 
2489
    int             print_color_mode)   /* I - Printer supports print-color-mode */
2400
2490
{
2401
2491
  int           i;                      /* Looping var */
2402
2492
  ipp_t         *request;               /* Request data */
2406
2496
                *media_size;            /* media-size value */
2407
2497
  const char    *media_source,          /* media-source value */
2408
2498
                *media_type,            /* media-type value */
2409
 
                *collate_str;           /* multiple-document-handling value */
 
2499
                *collate_str,           /* multiple-document-handling value */
 
2500
                *mandatory;             /* Mandatory attributes */
 
2501
  ipp_tag_t     group;                  /* Current group */
 
2502
  ipp_attribute_t *attr;                /* Current attribute */
 
2503
  const char    *color_attr_name;       /* Supported color attribute */
 
2504
  char          buffer[1024];           /* Value buffer */
2410
2505
 
2411
2506
 
2412
2507
 /*
2452
2547
  }
2453
2548
 
2454
2549
#ifdef HAVE_LIBZ
2455
 
  if (compression && op != IPP_CREATE_JOB)
 
2550
  if (compression && op != IPP_OP_CREATE_JOB && op != IPP_OP_VALIDATE_JOB)
2456
2551
  {
2457
2552
    ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
2458
2553
                 "compression", NULL, compression);
2470
2565
    {
2471
2566
      int       num_finishings = 0,     /* Number of finishing values */
2472
2567
                finishings[10];         /* Finishing enum values */
 
2568
      ppd_choice_t *choice;             /* Marked choice */
2473
2569
 
2474
2570
     /*
2475
2571
      * Send standard IPP attributes...
2476
2572
      */
2477
2573
 
 
2574
      fputs("DEBUG: Adding standard IPP operation/job attributes.\n", stderr);
 
2575
 
 
2576
      if (pc->password &&
 
2577
          (keyword = cupsGetOption("job-password", num_options,
 
2578
                                   options)) != NULL)
 
2579
      {
 
2580
        ippAddOctetString(request, IPP_TAG_OPERATION, "job-password",
 
2581
                          keyword, strlen(keyword));
 
2582
 
 
2583
        if ((keyword = cupsGetOption("job-password-encryption", num_options,
 
2584
                                     options)) == NULL)
 
2585
          keyword = "none";
 
2586
 
 
2587
        ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
 
2588
                     "job-password-encryption", NULL, keyword);
 
2589
      }
 
2590
 
 
2591
      if (pc->account_id)
 
2592
      {
 
2593
        if ((keyword = cupsGetOption("job-account-id", num_options,
 
2594
                                     options)) == NULL)
 
2595
          keyword = cupsGetOption("job-billing", num_options, options);
 
2596
 
 
2597
        if (keyword)
 
2598
          ippAddString(request, IPP_TAG_JOB, IPP_TAG_NAME, "job-account-id",
 
2599
                       NULL, keyword);
 
2600
      }
 
2601
 
 
2602
      if (pc->accounting_user_id)
 
2603
      {
 
2604
        if ((keyword = cupsGetOption("job-accounting-user-id", num_options,
 
2605
                                     options)) == NULL)
 
2606
          keyword = user;
 
2607
 
 
2608
        if (keyword)
 
2609
          ippAddString(request, IPP_TAG_JOB, IPP_TAG_NAME,
 
2610
                       "job-accounting-user-id", NULL, keyword);
 
2611
      }
 
2612
 
 
2613
      for (mandatory = (char *)cupsArrayFirst(pc->mandatory);
 
2614
           mandatory;
 
2615
           mandatory = (char *)cupsArrayNext(pc->mandatory))
 
2616
      {
 
2617
        if (strcmp(mandatory, "copies") &&
 
2618
            strcmp(mandatory, "destination-uris") &&
 
2619
            strcmp(mandatory, "finishings") &&
 
2620
            strcmp(mandatory, "job-account-id") &&
 
2621
            strcmp(mandatory, "job-accounting-user-id") &&
 
2622
            strcmp(mandatory, "job-password") &&
 
2623
            strcmp(mandatory, "job-password-encryption") &&
 
2624
            strcmp(mandatory, "media") &&
 
2625
            strncmp(mandatory, "media-col", 9) &&
 
2626
            strcmp(mandatory, "multiple-document-handling") &&
 
2627
            strcmp(mandatory, "output-bin") &&
 
2628
            strcmp(mandatory, "print-color-mode") &&
 
2629
            strcmp(mandatory, "print-quality") &&
 
2630
            strcmp(mandatory, "sides") &&
 
2631
            (keyword = cupsGetOption(mandatory, num_options, options)) != NULL)
 
2632
        {
 
2633
          _ipp_option_t *opt = _ippFindOption(mandatory);
 
2634
                                        /* Option type */
 
2635
          ipp_tag_t     value_tag = opt ? opt->value_tag : IPP_TAG_NAME;
 
2636
                                        /* Value type */
 
2637
 
 
2638
          switch (value_tag)
 
2639
          {
 
2640
            case IPP_TAG_INTEGER :
 
2641
            case IPP_TAG_ENUM :
 
2642
                ippAddInteger(request, IPP_TAG_JOB, value_tag, mandatory,
 
2643
                              atoi(keyword));
 
2644
                break;
 
2645
            case IPP_TAG_BOOLEAN :
 
2646
                ippAddBoolean(request, IPP_TAG_JOB, mandatory,
 
2647
                              !_cups_strcasecmp(keyword, "true"));
 
2648
                break;
 
2649
            case IPP_TAG_RANGE :
 
2650
                {
 
2651
                  int lower, upper;     /* Range */
 
2652
 
 
2653
                  if (sscanf(keyword, "%d-%d", &lower, &upper) != 2)
 
2654
                    lower = upper = atoi(keyword);
 
2655
 
 
2656
                  ippAddRange(request, IPP_TAG_JOB, mandatory, lower, upper);
 
2657
                }
 
2658
                break;
 
2659
            case IPP_TAG_STRING :
 
2660
                ippAddOctetString(request, IPP_TAG_JOB, mandatory, keyword,
 
2661
                                  strlen(keyword));
 
2662
                break;
 
2663
            default :
 
2664
                ippAddString(request, IPP_TAG_JOB, value_tag, mandatory,
 
2665
                             NULL, keyword);
 
2666
                break;
 
2667
          }
 
2668
        }
 
2669
      }
 
2670
 
2478
2671
      if ((keyword = cupsGetOption("PageSize", num_options, options)) == NULL)
2479
2672
        keyword = cupsGetOption("media", num_options, options);
2480
2673
 
2533
2726
 
2534
2727
      if ((keyword = cupsGetOption("output-bin", num_options,
2535
2728
                                   options)) == NULL)
2536
 
        keyword = _ppdCacheGetBin(pc, cupsGetOption("OutputBin", num_options,
2537
 
                                                    options));
 
2729
      {
 
2730
        if ((choice = ppdFindMarkedChoice(ppd, "OutputBin")) != NULL)
 
2731
          keyword = _ppdCacheGetBin(pc, choice->choice);
 
2732
      }
2538
2733
 
2539
2734
      if (keyword)
2540
2735
        ippAddString(request, IPP_TAG_JOB, IPP_TAG_KEYWORD, "output-bin",
2541
2736
                     NULL, keyword);
2542
2737
 
2543
 
      if ((keyword = cupsGetOption("output-mode", num_options,
 
2738
      color_attr_name = print_color_mode ? "print-color-mode" : "output-mode";
 
2739
 
 
2740
      if ((keyword = cupsGetOption("print-color-mode", num_options,
2544
2741
                                   options)) != NULL)
2545
 
        ippAddString(request, IPP_TAG_JOB, IPP_TAG_KEYWORD, "output-mode",
 
2742
        ippAddString(request, IPP_TAG_JOB, IPP_TAG_KEYWORD, color_attr_name,
2546
2743
                     NULL, keyword);
2547
 
      else if ((keyword = cupsGetOption("ColorModel", num_options,
2548
 
                                        options)) != NULL)
 
2744
      else if ((choice = ppdFindMarkedChoice(ppd, "ColorModel")) != NULL)
2549
2745
      {
2550
 
        if (!_cups_strcasecmp(keyword, "Gray"))
2551
 
          ippAddString(request, IPP_TAG_JOB, IPP_TAG_KEYWORD, "output-mode",
2552
 
                               NULL, "monochrome");
 
2746
        if (!_cups_strcasecmp(choice->choice, "Gray"))
 
2747
          ippAddString(request, IPP_TAG_JOB, IPP_TAG_KEYWORD,
 
2748
                       color_attr_name, NULL, "monochrome");
2553
2749
        else
2554
 
          ippAddString(request, IPP_TAG_JOB, IPP_TAG_KEYWORD, "output-mode",
2555
 
                           NULL, "color");
 
2750
          ippAddString(request, IPP_TAG_JOB, IPP_TAG_KEYWORD,
 
2751
                       color_attr_name, NULL, "color");
2556
2752
      }
2557
2753
 
2558
2754
      if ((keyword = cupsGetOption("print-quality", num_options,
2559
2755
                                   options)) != NULL)
2560
2756
        ippAddInteger(request, IPP_TAG_JOB, IPP_TAG_ENUM, "print-quality",
2561
2757
                      atoi(keyword));
2562
 
      else if ((keyword = cupsGetOption("cupsPrintQuality", num_options,
2563
 
                                        options)) != NULL)
 
2758
      else if ((choice = ppdFindMarkedChoice(ppd, "cupsPrintQuality")) != NULL)
2564
2759
      {
2565
 
        if (!_cups_strcasecmp(keyword, "draft"))
 
2760
        if (!_cups_strcasecmp(choice->choice, "draft"))
2566
2761
          ippAddInteger(request, IPP_TAG_JOB, IPP_TAG_ENUM, "print-quality",
2567
2762
                        IPP_QUALITY_DRAFT);
2568
 
        else if (!_cups_strcasecmp(keyword, "normal"))
 
2763
        else if (!_cups_strcasecmp(choice->choice, "normal"))
2569
2764
          ippAddInteger(request, IPP_TAG_JOB, IPP_TAG_ENUM, "print-quality",
2570
2765
                        IPP_QUALITY_NORMAL);
2571
 
        else if (!_cups_strcasecmp(keyword, "high"))
 
2766
        else if (!_cups_strcasecmp(choice->choice, "high"))
2572
2767
          ippAddInteger(request, IPP_TAG_JOB, IPP_TAG_ENUM, "print-quality",
2573
2768
                        IPP_QUALITY_HIGH);
2574
2769
      }
2577
2772
        ippAddString(request, IPP_TAG_JOB, IPP_TAG_KEYWORD, "sides",
2578
2773
                     NULL, keyword);
2579
2774
      else if (pc->sides_option &&
2580
 
               (keyword = cupsGetOption(pc->sides_option, num_options,
2581
 
                                        options)) != NULL)
 
2775
               (choice = ppdFindMarkedChoice(ppd, pc->sides_option)) != NULL)
2582
2776
      {
2583
 
        if (!_cups_strcasecmp(keyword, pc->sides_1sided))
 
2777
        if (!_cups_strcasecmp(choice->choice, pc->sides_1sided))
2584
2778
          ippAddString(request, IPP_TAG_JOB, IPP_TAG_KEYWORD, "sides",
2585
2779
                       NULL, "one-sided");
2586
 
        else if (!_cups_strcasecmp(keyword, pc->sides_2sided_long))
 
2780
        else if (!_cups_strcasecmp(choice->choice, pc->sides_2sided_long))
2587
2781
          ippAddString(request, IPP_TAG_JOB, IPP_TAG_KEYWORD, "sides",
2588
2782
                       NULL, "two-sided-long-edge");
2589
 
        if (!_cups_strcasecmp(keyword, pc->sides_2sided_short))
 
2783
        if (!_cups_strcasecmp(choice->choice, pc->sides_2sided_short))
2590
2784
          ippAddString(request, IPP_TAG_JOB, IPP_TAG_KEYWORD, "sides",
2591
2785
                       NULL, "two-sided-short-edge");
2592
2786
      }
2692
2886
      * When talking to another CUPS server, send all options...
2693
2887
      */
2694
2888
 
 
2889
      fputs("DEBUG: Adding all operation/job attributes.\n", stderr);
 
2890
      cupsEncodeOptions2(request, num_options, options, IPP_TAG_OPERATION);
2695
2891
      cupsEncodeOptions2(request, num_options, options, IPP_TAG_JOB);
2696
2892
    }
2697
2893
 
2699
2895
      ippAddInteger(request, IPP_TAG_JOB, IPP_TAG_INTEGER, "copies", copies);
2700
2896
  }
2701
2897
 
 
2898
  fprintf(stderr, "DEBUG: IPP/%d.%d %s #%d\n", version / 10, version % 10,
 
2899
          ippOpString(ippGetOperation(request)), ippGetRequestId(request));
 
2900
  for (group = IPP_TAG_ZERO, attr = ippFirstAttribute(request);
 
2901
       attr;
 
2902
       attr = ippNextAttribute(request))
 
2903
  {
 
2904
    const char *name = ippGetName(attr);
 
2905
 
 
2906
    if (!name)
 
2907
    {
 
2908
      group = IPP_TAG_ZERO;
 
2909
      continue;
 
2910
    }
 
2911
 
 
2912
    if (group != ippGetGroupTag(attr))
 
2913
    {
 
2914
      group = ippGetGroupTag(attr);
 
2915
      fprintf(stderr, "DEBUG: ---- %s ----\n", ippTagString(group));
 
2916
    }
 
2917
 
 
2918
    ippAttributeString(attr, buffer, sizeof(buffer));
 
2919
    fprintf(stderr, "DEBUG: %s %s%s %s\n", name,
 
2920
            ippGetCount(attr) > 1 ? "1setOf " : "",
 
2921
            ippTagString(ippGetValueTag(attr)), buffer);
 
2922
  }
 
2923
 
 
2924
  fprintf(stderr, "DEBUG: ---- %s ----\n", ippTagString(IPP_TAG_END));
 
2925
 
2702
2926
  return (request);
2703
2927
}
2704
2928
 
2714
2938
            const char *resource,       /* I - Resource path (not used) */
2715
2939
            int        *password_tries) /* I - Password tries */
2716
2940
{
 
2941
  char  def_username[HTTP_MAX_VALUE];   /* Default username */
 
2942
 
 
2943
 
2717
2944
  fprintf(stderr, "DEBUG: password_cb(prompt=\"%s\", http=%p, method=\"%s\", "
2718
2945
                  "resource=\"%s\", password_tries=%p(%d)), password=%p\n",
2719
2946
          prompt, http, method, resource, password_tries, *password_tries,
2729
2956
 
2730
2957
  auth_info_required = "username,password";
2731
2958
 
 
2959
  if (httpGetSubField(http, HTTP_FIELD_WWW_AUTHENTICATE, "username",
 
2960
                      def_username))
 
2961
  {
 
2962
    char        quoted[HTTP_MAX_VALUE * 2 + 4];
 
2963
                                        /* Quoted string */
 
2964
 
 
2965
    fprintf(stderr, "ATTR: auth-info-default=%s,\n",
 
2966
            quote_string(def_username, quoted, sizeof(quoted)));
 
2967
  }
 
2968
 
2732
2969
  if (password && *password && *password_tries < 3)
2733
2970
  {
2734
2971
    (*password_tries) ++;
2747
2984
 
2748
2985
 
2749
2986
/*
 
2987
 * 'quote_string()' - Quote a string value.
 
2988
 */
 
2989
 
 
2990
static const char *                     /* O - Quoted string */
 
2991
quote_string(const char *s,             /* I - String */
 
2992
             char       *q,             /* I - Quoted string buffer */
 
2993
             size_t     qsize)          /* I - Size of quoted string buffer */
 
2994
{
 
2995
  char  *qptr,                          /* Pointer into string buffer */
 
2996
        *qend;                          /* End of string buffer */
 
2997
 
 
2998
 
 
2999
  qptr = q;
 
3000
  qend = q + qsize - 5;
 
3001
 
 
3002
  if (qend < q)
 
3003
  {
 
3004
    *q = '\0';
 
3005
    return (q);
 
3006
  }
 
3007
 
 
3008
  *qptr++ = '\'';
 
3009
  *qptr++ = '\"';
 
3010
 
 
3011
  while (*s && qptr < qend)
 
3012
  {
 
3013
    if (*s == '\\' || *s == '\"' || *s == '\'')
 
3014
    {
 
3015
      if (q < (qend - 3))
 
3016
      {
 
3017
        *qptr++ = '\\';
 
3018
        *qptr++ = '\\';
 
3019
        *qptr++ = '\\';
 
3020
      }
 
3021
      else
 
3022
        break;
 
3023
    }
 
3024
 
 
3025
    *qptr++ = *s++;
 
3026
  }
 
3027
 
 
3028
  *qptr++ = '\"';
 
3029
  *qptr++ = '\'';
 
3030
  *qptr   = '\0';
 
3031
 
 
3032
  return (q);
 
3033
}
 
3034
 
 
3035
 
 
3036
/*
2750
3037
 * 'report_attr()' - Report an IPP attribute value.
2751
3038
 */
2752
3039
 
2755
3042
{
2756
3043
  int           i;                      /* Looping var */
2757
3044
  char          value[1024],            /* Value string */
2758
 
                *valptr,                /* Pointer into value string */
2759
 
                *attrptr;               /* Pointer into attribute value */
 
3045
                *valptr;                /* Pointer into value string */
2760
3046
  const char    *cached;                /* Cached attribute */
2761
3047
 
2762
3048
 
2783
3069
      case IPP_TAG_TEXT :
2784
3070
      case IPP_TAG_NAME :
2785
3071
      case IPP_TAG_KEYWORD :
2786
 
          *valptr++ = '\'';
2787
 
          *valptr++ = '\"';
2788
 
          for (attrptr = attr->values[i].string.text;
2789
 
               *attrptr && valptr < (value + sizeof(value) - 10);
2790
 
               attrptr ++)
2791
 
          {
2792
 
            if (*attrptr == '\\' || *attrptr == '\"' || *attrptr == '\'')
2793
 
            {
2794
 
              *valptr++ = '\\';
2795
 
              *valptr++ = '\\';
2796
 
              *valptr++ = '\\';
2797
 
            }
2798
 
 
2799
 
            *valptr++ = *attrptr;
2800
 
          }
2801
 
          *valptr++ = '\"';
2802
 
          *valptr++ = '\'';
 
3072
          quote_string(attr->values[i].string.text, valptr,
 
3073
                       value + sizeof(value) - valptr);
 
3074
          valptr += strlen(valptr);
2803
3075
          break;
2804
3076
 
2805
3077
      default :
3128
3400
 
3129
3401
  if (conn)
3130
3402
  {
3131
 
    xpc_connection_suspend(conn);
3132
3403
    xpc_connection_cancel(conn);
3133
3404
    xpc_release(conn);
3134
3405
  }
3250
3521
    else
3251
3522
      op = '\0';
3252
3523
 
3253
 
    new_reasons = _cupsArrayNewStrings(s);
 
3524
    new_reasons = _cupsArrayNewStrings(s, ',');
3254
3525
  }
3255
3526
  else
3256
3527
    return;
3394
3665
}
3395
3666
 
3396
3667
/*
3397
 
 * End of "$Id: ipp.c 11221 2013-08-06 16:16:01Z msweet $".
 
3668
 * End of "$Id: ipp.c 11353 2013-10-23 19:53:08Z msweet $".
3398
3669
 */