]> git.ipfire.org Git - thirdparty/cups.git/commitdiff
Import CUPS 1.4svn-r7170.
authormsweet <msweet@a1ca3aef-8c08-0410-bb20-df032aa958be>
Fri, 4 Jan 2008 02:32:38 +0000 (02:32 +0000)
committermsweet <msweet@a1ca3aef-8c08-0410-bb20-df032aa958be>
Fri, 4 Jan 2008 02:32:38 +0000 (02:32 +0000)
git-svn-id: svn+ssh://src.apple.com/svn/cups/easysw/current@567 a1ca3aef-8c08-0410-bb20-df032aa958be

19 files changed:
CHANGES-1.3.txt
CHANGES.txt
README.txt
backend/ipp.c
berkeley/lpr.c
cups/cups.h
cups/dest.c
cups/globals.h
cups/libcups.exp
cups/request.c
cups/util.c
data/testprint.ps
doc/index.html.in
man/cupsd.conf.man.in
man/lpadmin.man
man/lpq.man
pdftops/pdftops.cxx
systemv/lp.c
templates/trailer.tmpl

index 5822d1565f008f90948c2a1e1f8abf8cefc7e70a..c9e71da748cf825fa07230a5d1d300395c8aac08 100644 (file)
@@ -3,6 +3,11 @@ CHANGES-1.3.txt
 
 CHANGES IN CUPS V1.3.6
 
+       - Documentation updates (STR #2646, STR #2647, STR #2649)
+       - The PDF filter incorrectly filtered pages when page-ranges
+         and number-up were both specified (STR #2643)
+       - The IPP backend did not handle printing of pictwps files
+         to a non-Mac CUPS server properly.
        - The scheduler did not detect network interface changes
          on operating systems other than Mac OS X (STR #2631)
        - The scheduler now logs the UNIX error message when it
index 9d917f106ef42a070f9f2e6b00a2dccb19793296..3678d81640c974839948f9c4cfb6a7592b767d77 100644 (file)
@@ -1,8 +1,9 @@
-CHANGES.txt - 2007-12-19
+CHANGES.txt - 2008-01-03
 ------------------------
 
 CHANGES IN CUPS V1.4b1
 
+       - Added a new streaming request API (STR #2261)
        - Added a new cupsGetNamedDest() function to the CUPS
          library for faster printing with lp and lpr (STR #2638)
        - The scheduler now sets the PAM RHOST value on systems
index 48fee5a99a5afe9a2e7c26fb8cda7b6f7cde199c..10d72323999fd466aab9d306b0c167bd3015a76c 100644 (file)
@@ -1,5 +1,5 @@
-README - CUPS v1.3.0 - 2007-08-13
----------------------------------
+README - CUPS v1.4svn - 2008-01-02
+----------------------------------
 
 Looking for compile instructions?  Read the file "INSTALL.txt"
 instead...
@@ -153,9 +153,9 @@ PRINTING FILES
 
 LEGAL STUFF
 
-    CUPS is Copyright 2007 by Apple Inc.  CUPS, the CUPS logo, and
-    the Common UNIX Printing System are the trademark property of
-    Apple Inc.
+    CUPS is Copyright 2007-2008 by Apple Inc.  CUPS, the CUPS logo,
+    and the Common UNIX Printing System are the trademark property
+    of Apple Inc.
 
     The MD5 Digest code is Copyright 1999 Aladdin Enterprises.
 
index 95e598252a67e8b2a4b3a66f8842ddae96eff1be..3348cd5cf8975951902487f7736b8b01e2c8072b 100644 (file)
@@ -3,7 +3,7 @@
  *
  *   IPP backend for the Common UNIX Printing System (CUPS).
  *
- *   Copyright 2007 by Apple Inc.
+ *   Copyright 2007-2008 by Apple Inc.
  *   Copyright 1997-2007 by Easy Software Products, all rights reserved.
  *
  *   These coded instructions, statements, and computer programs are the
@@ -865,12 +865,13 @@ main(int  argc,                           /* I - Number of command-line args */
     num_options = cupsParseOptions(argv[5], 0, &options);
 
 #ifdef __APPLE__
-    if (!strcasecmp(content_type, "application/pictwps") && num_files == 1)
+    if (!strcasecmp(final_content_type, "application/pictwps") &&
+        num_files == 1)
     {
       if (format_sup != NULL)
       {
        for (i = 0; i < format_sup->num_values; i ++)
-         if (!strcasecmp(content_type, format_sup->values[i].string.text))
+         if (!strcasecmp(final_content_type, format_sup->values[i].string.text))
            break;
       }
 
index de01906bc6f740885bd79acfc41e7a2b783c5688..a1388be7e1c34b8f65d828ef08510fd2e5ac725b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: lpr.c 7017 2007-10-10 22:09:57Z mike $"
+ * "$Id: lpr.c 7170 2008-01-04 02:21:30Z mike $"
  *
  *   "lpr" command for the Common UNIX Printing System (CUPS).
  *
@@ -14,8 +14,7 @@
  *
  * Contents:
  *
- *   main()       - Parse options and send files for printing.
- *   sighandler() - Signal catcher for when we print from stdin...
+ *   main() - Parse options and send files for printing.
  */
 
 /*
 #include <cups/cups.h>
 #include <cups/i18n.h>
 
-#ifndef WIN32
-#  include <unistd.h>
-#  include <signal.h>
-
-
-/*
- * Local functions.
- */
-
-void   sighandler(int);
-#endif /* !WIN32 */
-
-
-/*
- * Globals...
- */
-
-char   tempfile[1024];         /* Temporary file for printing from stdin */
-
 
 /*
  * 'main()' - Parse options and send files for printing.
@@ -73,13 +53,6 @@ main(int  argc,                              /* I - Number of command-line arguments */
   cups_option_t        *options;               /* Options */
   int          deletefile;             /* Delete file after print? */
   char         buffer[8192];           /* Copy buffer */
-  ssize_t      bytes;                  /* Bytes copied */
-  off_t                filesize;               /* Size of temp file */
-  int          temp;                   /* Temporary file descriptor */
-#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
-  struct sigaction action;             /* Signal action */
-  struct sigaction oldaction;          /* Old signal action */
-#endif /* HAVE_SIGACTION && !HAVE_SIGSET */
 
 
   _cupsSetLocale(argv);
@@ -409,72 +382,38 @@ main(int  argc,                           /* I - Number of command-line arguments */
         unlink(files[i]);
     }
   }
-  else
+  else if ((job_id = cupsCreateJob(CUPS_HTTP_DEFAULT, printer,
+                                   title ? title : "(stdin)",
+                                   num_options, options)) > 0)
   {
-    num_files = 1;
-
-#ifndef WIN32
-#  if defined(HAVE_SIGSET)
-    sigset(SIGHUP, sighandler);
-    if (sigset(SIGINT, sighandler) == SIG_IGN)
-      sigset(SIGINT, SIG_IGN);
-    sigset(SIGTERM, sighandler);
-#  elif defined(HAVE_SIGACTION)
-    memset(&action, 0, sizeof(action));
-    action.sa_handler = sighandler;
-
-    sigaction(SIGHUP, &action, NULL);
-    sigaction(SIGINT, NULL, &oldaction);
-    if (oldaction.sa_handler != SIG_IGN)
-      sigaction(SIGINT, &action, NULL);
-    sigaction(SIGTERM, &action, NULL);
-#  else
-    signal(SIGHUP, sighandler);
-    if (signal(SIGINT, sighandler) == SIG_IGN)
-      signal(SIGINT, SIG_IGN);
-    signal(SIGTERM, sighandler);
-#  endif
-#endif /* !WIN32 */
-
-    if ((temp = cupsTempFd(tempfile, sizeof(tempfile))) < 0)
-    {
-      _cupsLangPrintf(stderr,
-                      _("%s: Error - unable to create temporary file "
-                       "\"%s\" - %s\n"),
-                     argv[0], tempfile, strerror(errno));
-      return (1);
-    }
+    http_status_t      status;         /* Write status */
+    const char         *format;        /* Document format */
+    ssize_t            bytes;          /* Bytes read */
 
-    while ((bytes = read(0, buffer, sizeof(buffer))) > 0)
-      if (write(temp, buffer, bytes) < 0)
-      {
-       _cupsLangPrintf(stderr,
-                       _("%s: Error - unable to write to temporary file "
-                         "\"%s\" - %s\n"),
-                       argv[0], tempfile, strerror(errno));
-        close(temp);
-        unlink(tempfile);
-       return (1);
-      }
 
-    filesize = lseek(temp, 0, SEEK_CUR);
-    close(temp);
+    if (cupsGetOption("raw", num_options, options))
+      format = CUPS_FORMAT_RAW;
+    else if ((format = cupsGetOption("document-format", num_options,
+                                     options)) == NULL)
+      format = CUPS_FORMAT_AUTO;
+
+    status = cupsStartDocument(CUPS_HTTP_DEFAULT, printer, job_id, NULL,
+                               format, 1);
 
-    if (filesize <= 0)
+    while (status == HTTP_CONTINUE &&
+           (bytes = read(0, buffer, sizeof(buffer))) > 0)
+      status = cupsWriteRequestData(CUPS_HTTP_DEFAULT, buffer, bytes);
+
+    if (status != HTTP_CONTINUE)
     {
       _cupsLangPrintf(stderr,
-                      _("%s: Error - stdin is empty, so no job has been sent.\n"),
-                     argv[0]);
-      unlink(tempfile);
+                     _("%s: Error - unable to queue from stdin - %s\n"),
+                     argv[0], httpStatus(status));
       return (1);
     }
 
-    if (title)
-      job_id = cupsPrintFile(printer, tempfile, title, num_options, options);
-    else
-      job_id = cupsPrintFile(printer, tempfile, "(stdin)", num_options, options);
-
-    unlink(tempfile);
+    if (cupsFinishDocument(CUPS_HTTP_DEFAULT, printer) != IPP_OK)
+      job_id = 0;
   }
 
   if (job_id < 1)
@@ -487,29 +426,6 @@ main(int  argc,                            /* I - Number of command-line arguments */
 }
 
 
-#ifndef WIN32
-/*
- * 'sighandler()' - Signal catcher for when we print from stdin...
- */
-
-void
-sighandler(int s)                      /* I - Signal number */
-{
- /*
-  * Remove the temporary file we're using to print from stdin...
-  */
-
-  unlink(tempfile);
-
- /*
-  * Exit...
-  */
-
-  exit(s);
-}
-#endif /* !WIN32 */
-
-
 /*
- * End of "$Id: lpr.c 7017 2007-10-10 22:09:57Z mike $".
+ * End of "$Id: lpr.c 7170 2008-01-04 02:21:30Z mike $".
  */
index e938dfa9479f3f4d3e8576b5fccfae014bea1b7a..187071682fab3c7e2d4a56044d5b2d12b489470b 100644 (file)
@@ -59,11 +59,19 @@ extern "C" {
  * Constants...
  */
 
-#  define CUPS_VERSION         1.0400
+#  define CUPS_VERSION         1.0399
 #  define CUPS_VERSION_MAJOR   1
 #  define CUPS_VERSION_MINOR   4
-#  define CUPS_VERSION_PATCH   0
-#  define CUPS_DATE_ANY                -1
+#  define CUPS_VERSION_PATCH   -1
+
+#  define CUPS_DATE_ANY                (time_t)-1
+#  define CUPS_FORMAT_AUTO     "application/octet-stream"
+#  define CUPS_FORMAT_PDF      "application/pdf"
+#  define CUPS_FORMAT_POSTSCRIPT "application/postscript"
+#  define CUPS_FORMAT_RAW      "application/vnd.cups-raw"
+#  define CUPS_FORMAT_TEXT     "text/plain"
+#  define CUPS_HTTP_DEFAULT    (http_t *)0
+#  define CUPS_LENGTH_VARIABLE (ssize_t)0
 
 
 /*
@@ -140,7 +148,7 @@ typedef struct cups_job_s           /**** Job ****/
  * Functions...
  */
 
-extern int             cupsCancelJob(const char *printer, int job);
+extern int             cupsCancelJob(const char *name, int job_id);
 extern ipp_t           *cupsDoFileRequest(http_t *http, ipp_t *request,
                                           const char *resource,
                                           const char *filename);
@@ -152,13 +160,13 @@ extern int                cupsGetClasses(char ***classes) _CUPS_DEPRECATED;
 extern const char      *cupsGetDefault(void);
 extern int             cupsGetJobs(cups_job_t **jobs, const char *dest,
                                    int myjobs, int completed);
-extern const char      *cupsGetPPD(const char *printer);
+extern const char      *cupsGetPPD(const char *name);
 extern int             cupsGetPrinters(char ***printers) _CUPS_DEPRECATED;
 extern ipp_status_t    cupsLastError(void);
-extern int             cupsPrintFile(const char *printer, const char *filename,
+extern int             cupsPrintFile(const char *name, const char *filename,
                                      const char *title, int num_options,
                                      cups_option_t *options);
-extern int             cupsPrintFiles(const char *printer, int num_files,
+extern int             cupsPrintFiles(const char *name, int num_files,
                                       const char **files, const char *title,
                                       int num_options, cups_option_t *options);
 extern char            *cupsTempFile(char *filename, int len) _CUPS_DEPRECATED;
@@ -206,14 +214,14 @@ extern http_status_t      cupsPutFd(http_t *http, const char *resource, int fd) _CUPS
 extern const char      *cupsGetDefault2(http_t *http) _CUPS_API_1_1_21;
 extern int             cupsGetDests2(http_t *http, cups_dest_t **dests) _CUPS_API_1_1_21;
 extern int             cupsGetJobs2(http_t *http, cups_job_t **jobs,
-                                    const char *dest, int myjobs,
+                                    const char *name, int myjobs,
                                     int completed) _CUPS_API_1_1_21;
-extern const char      *cupsGetPPD2(http_t *http, const char *printer) _CUPS_API_1_1_21;
-extern int             cupsPrintFile2(http_t *http, const char *printer,
+extern const char      *cupsGetPPD2(http_t *http, const char *name) _CUPS_API_1_1_21;
+extern int             cupsPrintFile2(http_t *http, const char *name,
                                       const char *filename,
                                       const char *title, int num_options,
                                       cups_option_t *options) _CUPS_API_1_1_21;
-extern int             cupsPrintFiles2(http_t *http, const char *printer,
+extern int             cupsPrintFiles2(http_t *http, const char *name,
                                        int num_files, const char **files,
                                        const char *title, int num_options,
                                        cups_option_t *options) _CUPS_API_1_1_21;
@@ -249,11 +257,30 @@ extern void               cupsSetDefaultDest(const char *name,
                                           cups_dest_t *dests) _CUPS_API_1_3;
 
 /**** New in CUPS 1.4 ****/
+extern ipp_status_t    cupsCancelJob2(http_t *http, int job_id, int purge);
+extern int             cupsCreateJob(http_t *http, const char *name,
+                                     const char *title, int num_options,
+                                     cups_option_t *options) _CUPS_API_1_4;
+extern ipp_status_t    cupsFinishDocument(http_t *http,
+                                          const char *name) _CUPS_API_1_4;
 extern cups_dest_t     *cupsGetNamedDest(http_t *http, const char *name,
                                          const char *instance) _CUPS_API_1_4;
 extern http_status_t   cupsGetPPD3(http_t *http, const char *name,
                                    time_t *modtime, char *buffer,
                                    size_t bufsize) _CUPS_API_1_4;
+extern ipp_t           *cupsGetResponse(http_t *http,
+                                        const char *resource) _CUPS_API_1_4;
+extern ssize_t         cupsReadResponseData(http_t *http, char *buffer,
+                                            size_t length) _CUPS_API_1_4;
+extern http_status_t   cupsSendRequest(http_t *http, ipp_t *request,
+                                       const char *resource,
+                                       size_t length) _CUPS_API_1_4;
+extern http_status_t   cupsStartDocument(http_t *http, const char *name,
+                                         int job_id, const char *docname,
+                                         const char *format,
+                                         int last_document) _CUPS_API_1_4;
+extern http_status_t   cupsWriteRequestData(http_t *http, const char *buffer,
+                                            size_t length) _CUPS_API_1_4;
 
 #  ifdef __cplusplus
 }
index 9f4fd212b3873ebc5cd47a23c16997a065d378a6..2b89784336fd97aafba70b5433328bac76a3d2c0 100644 (file)
@@ -265,20 +265,7 @@ cupsGetDest(const char  *name,             /* I - Destination name or NULL for the default
 int                                    /* O - Number of destinations */
 cupsGetDests(cups_dest_t **dests)      /* O - Destinations */
 {
-  int          num_dests;              /* Number of destinations */
-  _cups_globals_t *cg = _cupsGlobals();        /* Pointer to library globals */
-
-
- /*
-  * Connect to the CUPS server and get the destination list and options...
-  */
-
-  if (!cg->http)
-    cg->http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption());
-
-  num_dests = cupsGetDests2(cg->http, dests);
-
-  return (num_dests);
+  return (cupsGetDests2(CUPS_HTTP_DEFAULT, dests));
 }
 
 
@@ -297,7 +284,7 @@ cupsGetDests(cups_dest_t **dests)   /* O - Destinations */
  */
 
 int                                    /* O - Number of destinations */
-cupsGetDests2(http_t      *http,       /* I - HTTP connection */
+cupsGetDests2(http_t      *http,       /* I - HTTP connection or CUPS_HTTP_DEFAULT */
               cups_dest_t **dests)     /* O - Destinations */
 {
   int          i;                      /* Looping var */
@@ -310,14 +297,14 @@ cupsGetDests2(http_t      *http,  /* I - HTTP connection */
                *instance;              /* Pointer to instance name */
   int          num_reals;              /* Number of real queues */
   cups_dest_t  *reals;                 /* Real queues */
-  _cups_globals_t *cg = _cupsGlobals();        /* Global data */
+  _cups_globals_t *cg = _cupsGlobals();        /* Pointer to library globals */
 
 
  /*
   * Range check the input...
   */
 
-  if (!http || !dests)
+  if (!dests)
     return (0);
 
  /*
@@ -461,7 +448,8 @@ cupsGetDests2(http_t      *http,    /* I - HTTP connection */
  * If NULL is returned, the destination does not exist or there is no default
  * destination.
  *
- * If "http" is NULL, the connection to the default print server will be used.
+ * If "http" is CUPS_HTTP_DEFAULT, the connection to the default print server
+ * will be used.
  *
  * If "name" is NULL, the default printer for the current user will be returned.
  *
@@ -472,7 +460,7 @@ cupsGetDests2(http_t      *http,    /* I - HTTP connection */
  */
 
 cups_dest_t *                          /* O - Destination or NULL */
-cupsGetNamedDest(http_t     *http,     /* I - HTTP connection or NULL */
+cupsGetNamedDest(http_t     *http,     /* I - HTTP connection or CUPS_HTTP_DEFAULT */
                  const char *name,     /* I - Destination name or NULL */
                  const char *instance) /* I - Instance name or NULL */
 {
@@ -485,20 +473,6 @@ cupsGetNamedDest(http_t     *http, /* I - HTTP connection or NULL */
   _cups_globals_t *cg = _cupsGlobals();        /* Pointer to library globals */
 
 
- /*
-  * Connect to the server as needed...
-  */
-
-  if (!http)
-  {
-    if (!cg->http &&
-        (cg->http = httpConnectEncrypt(cupsServer(), ippPort(),
-                                       cupsEncryption())) == NULL)
-      return (NULL);
-
-    http = cg->http;
-  }
-
  /*
   * If "name" is NULL, find the default destination...
   */
@@ -634,7 +608,7 @@ cupsRemoveDest(const char  *name,   /* I  - Destination name */
 
 
 /*
- * 'cupsDestSetDefaultDest()' - Set the default destination.
+ * 'cupsSetDefaultDest()' - Set the default destination.
  *
  * @since CUPS 1.3@
  */
@@ -681,17 +655,7 @@ void
 cupsSetDests(int         num_dests,    /* I - Number of destinations */
              cups_dest_t *dests)       /* I - Destinations */
 {
-  _cups_globals_t *cg = _cupsGlobals();        /* Pointer to library globals */
-
-
- /*
-  * Connect to the CUPS server and save the destination list and options...
-  */
-
-  if (!cg->http)
-    cg->http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption());
-
-  cupsSetDests2(cg->http, num_dests, dests);
+  cupsSetDests2(CUPS_HTTP_DEFAULT, num_dests, dests);
 }
 
 
@@ -705,7 +669,7 @@ cupsSetDests(int         num_dests, /* I - Number of destinations */
  */
 
 int                                    /* O - 0 on success, -1 on error */
-cupsSetDests2(http_t      *http,       /* I - HTTP connection */
+cupsSetDests2(http_t      *http,       /* I - HTTP connection or CUPS_HTTP_DEFAULT */
               int         num_dests,   /* I - Number of destinations */
               cups_dest_t *dests)      /* I - Destinations */
 {
@@ -723,14 +687,14 @@ cupsSetDests2(http_t      *http,  /* I - HTTP connection */
   cups_dest_t  *temps,                 /* Temporary destinations */
                *temp;                  /* Current temporary dest */
   const char   *val;                   /* Value of temporary option */
-  _cups_globals_t *cg = _cupsGlobals();        /* Global data */
+  _cups_globals_t *cg = _cupsGlobals();        /* Pointer to library globals */
 
 
  /*
   * Range check the input...
   */
 
-  if (!http || !num_dests || !dests)
+  if (!num_dests || !dests)
     return (-1);
 
  /*
@@ -1155,7 +1119,7 @@ cups_get_dests(const char  *filename,     /* I - File to read from */
  */
 
 static int                             /* O - Number of destinations */
-cups_get_sdests(http_t      *http,     /* I - HTTP connection */
+cups_get_sdests(http_t      *http,     /* I - HTTP connection or CUPS_HTTP_DEFAULT */
                 ipp_op_t    op,                /* I - IPP operation */
                const char  *name,      /* I - Name of destination */
                 int         num_dests, /* I - Number of destinations */
index ac3dd83df0f90f08b9d4897169fd2fbfa94af9cc..b310461dd481dd103b3a01830c6f9685a19e9f8d 100644 (file)
@@ -124,6 +124,7 @@ typedef struct _cups_globals_s              /**** CUPS global state data ****/
  * Prototypes...
  */
 
+extern http_t          *_cupsConnect(void);
 extern const char      *_cupsGetPassword(const char *prompt);
 extern _cups_globals_t *_cupsGlobals(void);
 extern void            _cupsSetError(ipp_status_t status, const char *message);
index b68dedf8f73a9a5c844b7775e653caf4a2b2c693..f14668ef1ab76d0212b9ec63305735d6447714ce 100644 (file)
@@ -62,7 +62,9 @@ _cupsBackChannelRead
 _cupsBackChannelWrite
 _cupsBackendDeviceURI
 _cupsCancelJob
+_cupsCancelJob2
 _cupsCharsetToUTF8
+_cupsCreateJob
 _cupsDirClose
 _cupsDirOpen
 _cupsDirRead
@@ -100,6 +102,7 @@ _cupsFileStdout
 _cupsFileTell
 _cupsFileUnlock
 _cupsFileWrite
+_cupsFinishDocument
 _cupsFreeDests
 _cupsFreeJobs
 _cupsFreeOptions
@@ -120,6 +123,7 @@ _cupsGetPPD
 _cupsGetPPD2
 _cupsGetPPD3
 _cupsGetPrinters
+_cupsGetResponse
 _cupsGetServerPPD
 _cupsLangDefault
 _cupsLangEncoding
@@ -138,8 +142,10 @@ _cupsPrintFiles
 _cupsPrintFiles2
 _cupsPutFd
 _cupsPutFile
+_cupsReadResponseData
 _cupsRemoveDest
 _cupsRemoveOption
+_cupsSendRequest
 _cupsServer
 _cupsSetDefaultDest
 _cupsSetDests
@@ -151,6 +157,7 @@ _cupsSetUser
 _cupsSideChannelDoRequest
 _cupsSideChannelRead
 _cupsSideChannelWrite
+_cupsStartDocument
 _cupsTempFd
 _cupsTempFile
 _cupsTempFile2
@@ -158,6 +165,7 @@ _cupsUser
 _cupsUTF32ToUTF8
 _cupsUTF8ToCharset
 _cupsUTF8ToUTF32
+_cupsWriteRequestData
 _httpAddrAny
 _httpAddrConnect
 _httpAddrEqual
index 14741e95c801d011fb17e20b65ead2f102e86c3e..6544c3448fb5dcc6fcc6d2d842a9e608ac2697a9 100644 (file)
@@ -3,7 +3,7 @@
  *
  *   IPP utilities for the Common UNIX Printing System (CUPS).
  *
- *   Copyright 2007 by Apple Inc.
+ *   Copyright 2007-2008 by Apple Inc.
  *   Copyright 1997-2007 by Easy Software Products.
  *
  *   These coded instructions, statements, and computer programs are the
  *
  * Contents:
  *
- *   cupsDoFileRequest() - Do an IPP request with a file.
- *   cupsDoIORequest()   - Do an IPP request with file descriptors.
- *   cupsDoRequest()     - Do an IPP request.
- *   _cupsSetError()     - Set the last IPP status code and status-message.
- *   _cupsSetHTTPError() - Set the last error using the HTTP status.
+ *   cupsDoFileRequest()    - Do an IPP request with a file.
+ *   cupsDoIORequest()      - Do an IPP request with file descriptors.
+ *   cupsDoRequest()        - Do an IPP request.
+ *   cupsGetResponse()      - Get a response to an IPP request.
+ *   cupsReadResponseData() - Read additional data after the IPP response.
+ *   cupsSendRequest()      - Send an IPP request.
+ *   cupsWriteRequestData() - Write additional data after an IPP request.
+ *   _cupsSetError()        - Set the last IPP status code and status-message.
+ *   _cupsSetHTTPError()    - Set the last error using the HTTP status.
  */
 
 /*
@@ -52,7 +56,7 @@
  */
 
 ipp_t *                                        /* O - Response data */
-cupsDoFileRequest(http_t     *http,    /* I - HTTP connection to server */
+cupsDoFileRequest(http_t     *http,    /* I - HTTP connection or CUPS_HTTP_DEFAULT */
                   ipp_t      *request, /* I - IPP request */
                   const char *resource,        /* I - HTTP resource for POST */
                  const char *filename) /* I - File to send or NULL for none */
@@ -106,37 +110,44 @@ cupsDoFileRequest(http_t     *http,       /* I - HTTP connection to server */
  */
 
 ipp_t *                                        /* O - Response data */
-cupsDoIORequest(http_t     *http,      /* I - HTTP connection to server */
+cupsDoIORequest(http_t     *http,      /* I - HTTP connection or CUPS_HTTP_DEFAULT */
                 ipp_t      *request,   /* I - IPP request */
                 const char *resource,  /* I - HTTP resource for POST */
                int        infile,      /* I - File to read from or -1 for none */
                int        outfile)     /* I - File to write to or -1 for none */
 {
-  ipp_t                *response;              /* IPP response data */
-  size_t       length;                 /* Content-Length value */
+  ipp_t                *response = NULL;       /* IPP response data */
+  size_t       length = 0;             /* Content-Length value */
   http_status_t        status;                 /* Status of HTTP request */
-  int          got_status;             /* Did we get the status? */
-  ipp_state_t  state;                  /* State of IPP processing */
   struct stat  fileinfo;               /* File information */
   int          bytes;                  /* Number of bytes read/written */
   char         buffer[32768];          /* Output buffer */
-  http_status_t        expect;                 /* Expect: header to use */
 
 
-  DEBUG_printf(("cupsDoFileRequest(%p, %p, \'%s\', \'%s\')\n",
-                http, request, resource ? resource : "(null)",
-               filename ? filename : "(null)"));
+  DEBUG_printf(("cupsDoIORequest(http=%p, request=%p, resource=\"%s\""
+                "infile=%d, outfile=%d)\n", http, request,
+               resource ? resource : "(null)", infile, outfile));
+
+ /*
+  * Range check input...
+  */
 
-  if (http == NULL || request == NULL || resource == NULL)
+  if (!request || !resource)
   {
-    if (request != NULL)
-      ippDelete(request);
+    ippDelete(request);
 
-    _cupsSetError(IPP_INTERNAL_ERROR, NULL);
+    _cupsSetError(IPP_INTERNAL_ERROR, strerror(EINVAL));
 
     return (NULL);
   }
 
+ /*
+  * Get the default connection as needed...
+  */
+
+  if (!http)
+    http = _cupsConnect();
+
  /*
   * See if we have a file to send...
   */
@@ -149,7 +160,7 @@ cupsDoIORequest(http_t     *http,   /* I - HTTP connection to server */
       * Can't get file information!
       */
 
-      _cupsSetError(errno == ENOENT ? IPP_NOT_FOUND : IPP_NOT_AUTHORIZED,
+      _cupsSetError(errno == EBADF ? IPP_NOT_FOUND : IPP_NOT_AUTHORIZED,
                     strerror(errno));
 
       ippDelete(request);
@@ -173,8 +184,347 @@ cupsDoIORequest(http_t     *http, /* I - HTTP connection to server */
 
       return (NULL);
     }
+
+#ifndef WIN32
+    if (!S_ISREG(fileinfo.st_mode))
+      length = 0;                      /* Chunk when piping */
+    else
+#endif /* !WIN32 */
+    length = ippLength(request) + fileinfo.st_size;
+  }
+  else
+    length = ippLength(request);
+
+ /*
+  * Loop until we can send the request without authorization problems.
+  */
+
+  while (response == NULL)
+  {
+    DEBUG_puts("cupsDoFileRequest: setup...");
+
+   /*
+    * Send the request...
+    */
+
+    status = cupsSendRequest(http, request, resource, length);
+
+    DEBUG_printf(("cupsDoFileRequest: status=%d\n", status));
+
+    if (status == HTTP_CONTINUE && request->state == IPP_DATA && infile >= 0)
+    {
+      DEBUG_puts("cupsDoFileRequest: file write...");
+
+     /*
+      * Send the file with the request...
+      */
+
+#ifndef WIN32
+      if (S_ISREG(fileinfo.st_mode))
+#endif /* WIN32 */
+      lseek(infile, 0, SEEK_SET);
+
+      while ((bytes = (int)read(infile, buffer, sizeof(buffer))) > 0)
+      {
+       if (httpCheck(http))
+       {
+         if ((status = httpUpdate(http)) != HTTP_CONTINUE)
+           break;
+        }
+
+       if (httpWrite2(http, buffer, bytes) < bytes)
+          break;
+      }
+    }
+
+   /*
+    * Get the server's response...
+    */
+
+    if (status == HTTP_CONTINUE || status == HTTP_OK)
+    {
+      response = cupsGetResponse(http, resource);
+      status   = http->status;
+    }
+
+    if (response)
+    {
+      if (outfile >= 0)
+      {
+       /*
+        * Write trailing data to file...
+       */
+
+       while ((bytes = (int)httpRead2(http, buffer, sizeof(buffer))) > 0)
+         if (write(outfile, buffer, bytes) < bytes)
+           break;
+      }
+      else
+      {
+       /*
+        * Flush any remaining data...
+        */
+
+        httpFlush(http);
+      }
+    }
+  }
+
+ /*
+  * Delete the original request and return the response...
+  */
+  
+  ippDelete(request);
+
+  return (response);
+}
+
+
+/*
+ * 'cupsDoRequest()' - Do an IPP request.
+ *
+ * This function sends the IPP request to the specified server, retrying
+ * and authenticating as necessary.  The request is freed with ippDelete()
+ * after receiving a valid IPP response.
+ */
+
+ipp_t *                                        /* O - Response data */
+cupsDoRequest(http_t     *http,                /* I - HTTP connection or CUPS_HTTP_DEFAULT */
+              ipp_t      *request,     /* I - IPP request */
+              const char *resource)    /* I - HTTP resource for POST */
+{
+  return (cupsDoFileRequest(http, request, resource, NULL));
+}
+
+
+/*
+ * 'cupsGetResponse()' - Get a response to an IPP request.
+ *
+ * Use this function to get the response for an IPP request sent using
+ * cupsSendDocument() or cupsSendRequest(). For requests that return
+ * additional data, use httpRead() after getting a successful response.
+ *
+ * @since CUPS 1.4@
+ */
+
+ipp_t *                                        /* O - Response or NULL on HTTP error */
+cupsGetResponse(http_t     *http,      /* I - HTTP connection or CUPS_HTTP_DEFAULT */
+                const char *resource)  /* I - HTTP resource for POST */
+{
+  http_status_t        status;                 /* HTTP status */
+  ipp_state_t  state;                  /* IPP read state */
+  ipp_t                *response = NULL;       /* IPP response */
+
+
+  DEBUG_printf(("cupsGetReponse(http=%p)\n", http));
+
+ /*
+  * Connect to the default server as needed...
+  */
+
+  if (!http)
+    http = _cupsConnect();
+
+  if (!http || (http->state != HTTP_POST_RECV && http->state != HTTP_POST_SEND))
+    return (NULL);
+
+ /*
+  * Check for an unfinished chunked request...
+  */
+
+  if (http->data_encoding == HTTP_ENCODE_CHUNKED)
+  {
+   /*
+    * Send a 0-length chunk to finish off the request...
+    */
+
+    DEBUG_puts("cupsGetResponse: Finishing chunked POST...");
+
+    if (httpWrite2(http, "", 0) < 0)
+      return (NULL);
+  }
+
+ /*
+  * Wait for a response from the server...
+  */
+
+  DEBUG_puts("cupsGetResponse: update...");
+
+  while ((status = httpUpdate(http)) == HTTP_CONTINUE)
+    /* Do nothing but update */;
+
+  DEBUG_printf(("cupsGetResponse: status = %d\n", status));
+
+  if (status == HTTP_OK)
+  {
+   /*
+    * Get the IPP response...
+    */
+
+    response = ippNew();
+
+    while ((state = ippRead(http, response)) != IPP_DATA)
+      if (state == IPP_ERROR)
+       break;
+
+    if (state == IPP_ERROR)
+    {
+     /*
+      * Delete the response...
+      */
+
+      DEBUG_puts("IPP read error!");
+
+      ippDelete(response);
+      response = NULL;
+
+      _cupsSetError(IPP_SERVICE_UNAVAILABLE, strerror(errno));
+    }
+  }
+  else if (status != HTTP_ERROR)
+  {
+   /*
+    * Flush any error message...
+    */
+
+    httpFlush(http);
+
+   /*
+    * Then handle encryption and authentication...
+    */
+
+    if (status == HTTP_UNAUTHORIZED)
+    {
+     /*
+      * See if we can do authentication...
+      */
+
+      DEBUG_puts("cupsGetResponse: Need authorization...");
+
+      if (!cupsDoAuthentication(http, "POST", resource))
+       httpReconnect(http);
+    }
+
+#ifdef HAVE_SSL
+    else if (status == HTTP_UPGRADE_REQUIRED)
+    {
+     /*
+      * Force a reconnect with encryption...
+      */
+
+      DEBUG_puts("cupsGetResponse: Need encryption...");
+
+      if (!httpReconnect(http))
+        httpEncryption(http, HTTP_ENCRYPT_REQUIRED);
+    }
+#endif /* HAVE_SSL */
+  }
+
+  if (response)
+  {
+    ipp_attribute_t    *attr;          /* status-message attribute */
+
+
+    attr = ippFindAttribute(response, "status-message", IPP_TAG_TEXT);
+
+    _cupsSetError(response->request.status.status_code,
+                   attr ? attr->values[0].string.text :
+                      ippErrorString(response->request.status.status_code));
+  }
+  else if (status != HTTP_OK)
+    _cupsSetHTTPError(status);
+
+  return (response);
+}
+
+
+/*
+ * 'cupsReadResponseData()' - Read additional data after the IPP response.
+ *
+ * This function is used after cupsGetResponse() to read the PPD or document
+ * files for CUPS_GET_PPD and CUPS_GET_DOCUMENT requests, respectively.
+ *
+ * @since CUPS 1.4@
+ */
+
+ssize_t                                        /* O - Bytes read, 0 on EOF, -1 on error */
+cupsReadResponseData(
+    http_t *http,                      /* I - HTTP connection or CUPS_HTTP_DEFAULT */
+    char   *buffer,                    /* I - Buffer to use */
+    size_t length)                     /* I - Number of bytes to read */
+{
+ /*
+  * Get the default connection as needed...
+  */
+
+  if (!http)
+  {
+    _cups_globals_t *cg = _cupsGlobals();
+                                       /* Pointer to library globals */
+
+    if ((http = cg->http) == NULL)
+    {
+      _cupsSetError(IPP_INTERNAL_ERROR, "No active connection");
+      return (-1);
+    }
   }
 
+ /*
+  * Then read from the HTTP connection...
+  */
+
+  return (httpRead2(http, buffer, length));
+}
+
+
+/*
+ * 'cupsSendRequest()' - Send an IPP request.
+ *
+ * Use httpWrite() to write any additional data (document, PPD file, etc.)
+ * for the request, cupsGetResponse() to get the IPP response, and httpRead()
+ * to read any additional data following the response. Only one request can be 
+ * sent/queued at a time.
+ *
+ * Unlike cupsDoFileRequest(), cupsDoIORequest(), and cupsDoRequest(), the
+ * request is not freed.
+ *
+ * @since CUPS 1.4@
+ */
+
+http_status_t                          /* O - Initial HTTP status */
+cupsSendRequest(http_t     *http,      /* I - HTTP connection or CUPS_HTTP_DEFAULT */
+                ipp_t      *request,   /* I - IPP request */
+                const char *resource,  /* I - Resource path */
+               size_t     length)      /* I - Length of data to follow or CUPS_LENGTH_VARIABLE */
+{
+  http_status_t        status;                 /* Status of HTTP request */
+  int          got_status;             /* Did we get the status? */
+  ipp_state_t  state;                  /* State of IPP processing */
+  http_status_t        expect;                 /* Expect: header to use */
+
+
+  DEBUG_printf(("cupsSendRequest(http=%p, request=%p, resource=\"%s\", "
+                "length=" CUPS_LLFMT ")\n", http, request,
+               resource ? resource : "(null)", CUPS_LLCAST length));
+
+ /*
+  * Range check input...
+  */
+
+  if (!request || !resource)
+  {
+    _cupsSetError(IPP_INTERNAL_ERROR, strerror(EINVAL));
+
+    return (HTTP_ERROR);
+  }
+
+ /*
+  * Get the default connection as needed...
+  */
+
+  if (!http)
+    http = _cupsConnect();
+
 #ifdef HAVE_SSL
  /*
   * See if we have an auth-info attribute and are communicating over
@@ -185,57 +535,42 @@ cupsDoIORequest(http_t     *http, /* I - HTTP connection to server */
   if (ippFindAttribute(request, "auth-info", IPP_TAG_TEXT) &&
       !httpAddrLocalhost(http->hostaddr) && !http->tls &&
       httpEncryption(http, HTTP_ENCRYPT_REQUIRED))
-    return (NULL);
+    return (HTTP_ERROR);
 #endif /* HAVE_SSL */
 
  /*
   * Loop until we can send the request without authorization problems.
   */
 
-  response = NULL;
-  status   = HTTP_ERROR;
-  expect   = HTTP_CONTINUE;
+  status = HTTP_ERROR;
+  expect = HTTP_CONTINUE;
 
-  while (response == NULL)
+  for (;;)
   {
-    DEBUG_puts("cupsDoFileRequest: setup...");
+    DEBUG_puts("cupsSendRequest: setup...");
 
    /*
     * Setup the HTTP variables needed...
     */
 
-    length = ippLength(request);
-    if (infile >= 0)
-    {
-#ifndef WIN32
-      if (!S_ISREG(fileinfo.st_mode))
-        length = 0;                    /* Chunk when piping */
-      else
-#endif /* !WIN32 */
-      length += fileinfo.st_size;
-    }
-
     httpClearFields(http);
     httpSetLength(http, length);
     httpSetField(http, HTTP_FIELD_CONTENT_TYPE, "application/ipp");
     httpSetField(http, HTTP_FIELD_AUTHORIZATION, http->authstring);
     httpSetExpect(http, expect);
 
-    DEBUG_printf(("cupsDoFileRequest: authstring=\"%s\"\n", http->authstring));
+    DEBUG_printf(("cupsSendRequest: authstring=\"%s\"\n", http->authstring));
 
    /*
     * Try the request...
     */
 
-    DEBUG_puts("cupsDoFileRequest: post...");
+    DEBUG_puts("cupsSendRequest: post...");
 
     if (httpPost(http, resource))
     {
       if (httpReconnect(http))
-      {
-        status = HTTP_ERROR;
-        break;
-      }
+        return (HTTP_ERROR);
       else
         continue;
     }
@@ -244,7 +579,7 @@ cupsDoIORequest(http_t     *http,   /* I - HTTP connection to server */
     * Send the IPP data...
     */
 
-    DEBUG_puts("cupsDoFileRequest: ipp write...");
+    DEBUG_puts("cupsSendRequest: ipp write...");
 
     request->state = IPP_IDLE;
     status         = HTTP_CONTINUE;
@@ -261,222 +596,115 @@ cupsDoIORequest(http_t     *http,       /* I - HTTP connection to server */
          break;
       }
 
-    if (!got_status)
-    {
-     /*
-      * Wait up to 1 second to get the 100-continue response...
-      */
+   /*
+    * Wait up to 1 second to get the 100-continue response as needed...
+    */
 
+    if (!got_status && expect == HTTP_CONTINUE)
+    {
       if (httpWait(http, 1000))
         status = httpUpdate(http);
     }
     else if (httpCheck(http))
       status = httpUpdate(http);
 
-    if (status == HTTP_CONTINUE && state == IPP_DATA && infile >= 0)
-    {
-      DEBUG_puts("cupsDoFileRequest: file write...");
-
-     /*
-      * Send the file...
-      */
-
-#ifndef WIN32
-      if (S_ISREG(fileinfo.st_mode))
-#endif /* WIN32 */
-      lseek(infile, 0, SEEK_SET);
-
-      while ((bytes = (int)read(infile, buffer, sizeof(buffer))) > 0)
-      {
-       if (httpCheck(http))
-       {
-         if ((status = httpUpdate(http)) != HTTP_CONTINUE)
-           break;
-        }
-
-       if (httpWrite2(http, buffer, bytes) < bytes)
-          break;
-      }
-    }
-
    /*
-    * Get the server's return status...
+    * Process the current HTTP status...
     */
 
-    DEBUG_puts("cupsDoFileRequest: update...");
-
-    while (status == HTTP_CONTINUE)
-      status = httpUpdate(http);
-
-    DEBUG_printf(("cupsDoFileRequest: status = %d\n", status));
-
-    if (status == HTTP_UNAUTHORIZED)
+    switch (status)
     {
-      DEBUG_puts("cupsDoFileRequest: unauthorized...");
-
-     /*
-      * Flush any error message...
-      */
-
-      httpFlush(http);
-
-     /*
-      * See if we can do authentication...
-      */
-
-      if (cupsDoAuthentication(http, "POST", resource))
-        break;
+      case HTTP_ERROR :
+      case HTTP_CONTINUE :
+      case HTTP_OK :
+          return (status);
 
-      if (httpReconnect(http))
-      {
-        status = HTTP_ERROR;
-       break;
-      }
+      case HTTP_UNAUTHORIZED :
+          if (!cupsDoAuthentication(http, "POST", resource))
+           if (httpReconnect(http))
+             return (HTTP_ERROR);
 
-      continue;
-    }
-    else if (status == HTTP_ERROR)
-    {
-      DEBUG_printf(("cupsDoFileRequest: http->error=%d (%s)\n", http->error,
-                    strerror(http->error)));
+          return (status);
 
-#ifdef WIN32
-      if (http->error != WSAENETDOWN && http->error != WSAENETUNREACH &&
-          http->error != WSAETIMEDOUT)
-#else
-      if (http->error != ENETDOWN && http->error != ENETUNREACH &&
-          http->error != ETIMEDOUT)
-#endif /* WIN32 */
-        continue;
-      else
-        break;
-    }
 #ifdef HAVE_SSL
-    else if (status == HTTP_UPGRADE_REQUIRED)
-    {
-      /* Flush any error message... */
-      httpFlush(http);
+      case HTTP_UPGRADE_REQUIRED :
+        /*
+         * Flush any error message, reconnect, and then upgrade with
+         * encryption...
+         */
 
-      /* Reconnect... */
-      if (httpReconnect(http))
-      {
-        status = HTTP_ERROR;
-        break;
-      }
+         if (httpReconnect(http))
+           return (HTTP_ERROR);
 
-      /* Upgrade with encryption... */
-      httpEncryption(http, HTTP_ENCRYPT_REQUIRED);
+         httpEncryption(http, HTTP_ENCRYPT_REQUIRED);
 
-      /* Try again, this time with encryption enabled... */
-      continue;
-    }
+          return (status);
 #endif /* HAVE_SSL */
-    else if (status == HTTP_EXPECTATION_FAILED)
-    {
-     /*
-      * Don't try using the Expect: header the next time around...
-      */
 
-      expect = (http_status_t)0;
-    }
-    else if (status != HTTP_OK)
-    {
-      DEBUG_printf(("cupsDoFileRequest: error %d...\n", status));
+      case HTTP_EXPECTATION_FAILED :
+        /*
+         * Don't try using the Expect: header the next time around...
+         */
 
-     /*
-      * Flush any error message...
-      */
+         expect = (http_status_t)0;
 
-      httpFlush(http);
-      break;
-    }
-    else
-    {
-     /*
-      * Read the response...
-      */
-
-      DEBUG_puts("cupsDoFileRequest: response...");
-
-      response = ippNew();
-
-      while ((state = ippRead(http, response)) != IPP_DATA)
-       if (state == IPP_ERROR)
-         break;
-
-      if (state == IPP_ERROR)
-      {
-       /*
-        * Delete the response...
-       */
-
-        DEBUG_puts("IPP read error!");
-       ippDelete(response);
-       response = NULL;
-
-        _cupsSetError(IPP_SERVICE_UNAVAILABLE, strerror(errno));
-
-       break;
-      }
-      else if (outfile >= 0)
-      {
-       /*
-        * Write trailing data to file...
-       */
-
-       while ((bytes = (int)httpRead2(http, buffer, sizeof(buffer))) > 0)
-         if (write(outfile, buffer, bytes) < bytes)
-           break;
-      }
-      else
-      {
-       /*
-        * Flush any remaining data...
-        */
+      default :
+         /*
+         * Some other error...
+         */
 
-        httpFlush(http);
-      }
+         return (status);
     }
   }
+}
+
+
+/*
+ * 'cupsWriteRequestData()' - Write additional data after an IPP request.
+ *
+ * This function is used after cupsSendRequest() or cupsStartDocument()
+ * to provide a PPD or document file as needed.
+ *
+ * @since CUPS 1.4@
+ */
 
+http_status_t                          /* O - HTTP_CONTINUE if OK or HTTP status on error */
+cupsWriteRequestData(
+    http_t     *http,                  /* I - HTTP connection or CUPS_HTTP_DEFAULT */
+    const char *buffer,                        /* I - Bytes to write */
+    size_t     length)                 /* I - Number of bytes to write */
+{
  /*
-  * Delete the original request and return the response...
+  * Get the default connection as needed...
   */
-  
-  ippDelete(request);
 
-  if (response)
+  if (!http)
   {
-    ipp_attribute_t    *attr;          /* status-message attribute */
-
+    _cups_globals_t *cg = _cupsGlobals();
+                                       /* Pointer to library globals */
 
-    attr = ippFindAttribute(response, "status-message", IPP_TAG_TEXT);
-
-    _cupsSetError(response->request.status.status_code,
-                   attr ? attr->values[0].string.text :
-                      ippErrorString(response->request.status.status_code));
+    if ((http = cg->http) == NULL)
+    {
+      _cupsSetError(IPP_INTERNAL_ERROR, "No active connection");
+      return (HTTP_ERROR);
+    }
   }
-  else if (status != HTTP_OK)
-    _cupsSetHTTPError(status);
 
-  return (response);
-}
+ /*
+  * Then write to the HTTP connection...
+  */
 
+  if (httpWrite2(http, buffer, length) < 0)
+    return (HTTP_ERROR);
 
-/*
- * 'cupsDoRequest()' - Do an IPP request.
- *
- * This function sends the IPP request to the specified server, retrying
- * and authenticating as necessary.  The request is freed with ippDelete()
- * after receiving a valid IPP response.
- */
+ /*
+  * Finally, check if we have any pending data from the server...
+  */
 
-ipp_t *                                        /* O - Response data */
-cupsDoRequest(http_t     *http,                /* I - HTTP connection to server */
-              ipp_t      *request,     /* I - IPP request */
-              const char *resource)    /* I - HTTP resource for POST */
-{
-  return (cupsDoFileRequest(http, request, resource, NULL));
+  if (httpCheck(http))
+    return (httpUpdate(http));
+  else
+    return (HTTP_CONTINUE);
 }
 
 
index 142c70a7af2152ab52ecc3e9b02630227bde0e0d..33ba350537c2b523f2232cf738ccf218a516f637 100644 (file)
@@ -3,7 +3,7 @@
  *
  *   Printing utilities for the Common UNIX Printing System (CUPS).
  *
- *   Copyright 2007 by Apple Inc.
+ *   Copyright 2007-2008 by Apple Inc.
  *   Copyright 1997-2006 by Easy Software Products.
  *
  *   These coded instructions, statements, and computer programs are the
  * Contents:
  *
  *   cupsCancelJob()        - Cancel a print job on the default server.
+ *   cupsCancelJob2()       - Cancel or purge a print job.
+ *   cupsCreateJob()        - Create an empty job.
+ *   cupsFinishDocument()   - Finish sending a document.
  *   cupsFreeJobs()         - Free memory used by job data.
  *   cupsGetClasses()       - Get a list of printer classes from the default
  *                            server.
- *   cupsGetDefault()       - Get the default printer or class from the default
+ *   cupsGetDefault()       - Get the default printer or class for the default
+ *                            server.
+ *   cupsGetDefault2()      - Get the default printer or class for the specified
  *                            server.
- *   cupsGetDefault2()      - Get the default printer or class from the
- *                            specified server.
  *   cupsGetJobs()          - Get the jobs from the default server.
  *   cupsGetJobs2()         - Get the jobs from the specified server.
  *   cupsGetPPD()           - Get the PPD file for a printer on the default
  *                            server.
- *   cupsGetPPD2()          - Get the PPD file for a printer on the specified
+ *   cupsGetPPD2()          - Get the PPD file for a printer from the specified
  *                            server.
  *   cupsGetPPD3()          - Get the PPD file for a printer on the specified
  *                            server if it has changed.
@@ -44,7 +47,9 @@
  *                            the default server.
  *   cupsPrintFiles2()      - Print one or more files to a printer or class on
  *                            the specified server.
- *   cups_connect()         - Connect to the specified host...
+ *   cupsStartDocument()    - Add a document to a job created with
+ *                            cupsCreateJob().
+ *   _cupsConnect()         - Get the default server connection...
  *   cups_get_printer_uri() - Get the printer-uri-supported attribute for the
  *                            first printer in a class.
  */
@@ -70,7 +75,6 @@
  * Local functions...
  */
 
-static char    *cups_connect(const char *name, char *printer, char *hostname);
 static int     cups_get_printer_uri(http_t *http, const char *name,
                                     char *host, int hostsize, int *port,
                                     char *resource, int resourcesize,
@@ -86,38 +90,51 @@ static int  cups_get_printer_uri(http_t *http, const char *name,
 
 int                                    /* O - 1 on success, 0 on failure */
 cupsCancelJob(const char *name,                /* I - Name of printer or class */
-              int        job)          /* I - Job ID */
+              int        job_id)       /* I - Job ID */
 {
-  char         printer[HTTP_MAX_URI],  /* Printer name */
-               hostname[HTTP_MAX_URI], /* Hostname */
-               uri[HTTP_MAX_URI];      /* Printer URI */
-  ipp_t                *request,               /* IPP request */
-               *response;              /* IPP response */
-  _cups_globals_t *cg = _cupsGlobals();        /* Pointer to library globals */
+  return (cupsCancelJob2(CUPS_HTTP_DEFAULT, job_id, 0)
+              < IPP_REDIRECTION_OTHER_SITE);
+}
+
+
+/*
+ * 'cupsCancelJob2()' - Cancel or purge a print job.
+ *
+ * Canceled jobs remain in the job history while purged jobs are removed
+ * from the job history.
+ *
+ * Use the cupsLastError() and cupsLastErrorString() functions to get
+ * the cause of any failure.
+ *
+ * @since CUPS 1.4@
+ */
+
+ipp_status_t                           /* O - IPP status */
+cupsCancelJob2(http_t *http,           /* I - HTTP connection or CUPS_HTTP_DEFAULT */
+               int    job_id,          /* I - Job ID */
+              int    purge)            /* I - 1 to purge, 0 to cancel */
+{
+  char         uri[HTTP_MAX_URI];      /* Job URI */
+  ipp_t                *request;               /* IPP request */
 
 
  /*
-  * See if we can connect to the server...
+  * Range check input...
   */
 
-  if (!cups_connect(name, printer, hostname))
+  if (job_id <= 0)
   {
-    DEBUG_puts("Unable to connect to server!");
-
+    _cupsSetError(IPP_INTERNAL_ERROR, strerror(EINVAL));
     return (0);
   }
 
  /*
-  * Create a printer URI...
+  * Connect to the default server as needed...
   */
 
-  if (httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
-                       "localhost", 0, "/printers/%s", printer) != HTTP_URI_OK)
-  {
-    _cupsSetError(IPP_INTERNAL_ERROR, NULL);
-
-    return (0);
-  }
+  if (!http)
+    if ((http = _cupsConnect()) == NULL)
+      return (IPP_SERVICE_UNAVAILABLE);
 
  /*
   * Build an IPP_CANCEL_JOB request, which requires the following
@@ -125,29 +142,130 @@ cupsCancelJob(const char *name,          /* I - Name of printer or class */
   *
   *    attributes-charset
   *    attributes-natural-language
-  *    printer-uri
-  *    job-id
-  *    [requesting-user-name]
+  *    job-uri
+  *    requesting-user-name
+  *    [purge-job]
   */
 
   request = ippNewRequest(IPP_CANCEL_JOB);
 
-  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
-               NULL, uri);
-
-  ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_INTEGER, "job-id", job);
+  snprintf(uri, sizeof(uri), "ipp://localhost/jobs/%d", job_id);
 
+  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri", NULL, uri);
   ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
                NULL, cupsUser());
+  if (purge)
+    ippAddBoolean(request, IPP_TAG_OPERATION, "purge-job", 1);
 
  /*
   * Do the request...
   */
 
-  if ((response = cupsDoRequest(cg->http, request, "/jobs/")) != NULL)
-    ippDelete(response);
+  ippDelete(cupsDoRequest(http, request, "/jobs/"));
+
+  return (cupsLastError());
+}
+
+
+/*
+ * 'cupsCreateJob()' - Create an empty job.
+ *
+ * Submit files for printing to the job using the cupsStartDocument(),
+ * cupsWriteRequestData(), and cupsFinishDocument() functions.
+ *
+ * @since CUPS 1.4@
+ */
+
+int                                    /* O - Job ID or 0 on error */
+cupsCreateJob(
+    http_t        *http,               /* I - HTTP connection or CUPS_HTTP_DEFAULT */
+    const char    *name,               /* I - Printer or class name */
+    const char    *title,              /* I - Title of job */
+    int           num_options,         /* I - Number of options */
+    cups_option_t *options)            /* I - Options */
+{
+  char         printer_uri[1024],      /* Printer URI */
+               resource[1024];         /* Printer resource */
+  ipp_t                *request,               /* Create-Job request */
+               *response;              /* Create-Job response */
+  ipp_attribute_t *attr;               /* job-id attribute */
+  int          job_id = 0;             /* job-id value */
+
+
+  DEBUG_printf(("cupsCreateJob(http=%p, name=\"%s\", title=\"%s\", "
+                "num_options=%d, options=%p)\n",
+                http, name, title, num_options, options));
+
+ /*
+  * Range check input...
+  */
+
+  if (!name)
+  {
+    _cupsSetError(IPP_INTERNAL_ERROR, NULL);
+    return (0);
+  }
+
+ /*
+  * Build a Create-Job request...
+  */
+
+  if ((request = ippNewRequest(IPP_CREATE_JOB)) == NULL)
+  {
+    _cupsSetError(IPP_INTERNAL_ERROR, NULL);
+    return (0);
+  }
+
+  httpAssembleURIf(HTTP_URI_CODING_ALL, printer_uri, sizeof(printer_uri), "ipp",
+                   NULL, "localhost", ippPort(), "/printers/%s", name);
+  snprintf(resource, sizeof(resource), "/printers/%s", name);
+
+  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
+               NULL, printer_uri);
+  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
+               NULL, cupsUser());
+  if (title)
+    ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "job-name", NULL,
+                 title);
+  cupsEncodeOptions(request, num_options, options);
+
+ /*
+  * Send the request and get the job-id...
+  */
+
+  response = cupsDoRequest(http, request, resource);
+
+  if ((attr = ippFindAttribute(response, "job-id", IPP_TAG_INTEGER)) != NULL)
+    job_id = attr->values[0].integer;
 
-  return (cg->last_error < IPP_REDIRECTION_OTHER_SITE);
+  ippDelete(response);
+
+ /*
+  * Return it...
+  */
+
+  return (job_id);
+}
+
+
+/*
+ * 'cupsFinishDocument()' - Finish sending a document.
+ *
+ * @since CUPS 1.4@
+ */
+
+ipp_status_t                           /* O - Status of document submission */
+cupsFinishDocument(http_t     *http,   /* I - HTTP connection or CUPS_HTTP_DEFAULT */
+                   const char *name)   /* I - Printer or class name */
+{
+  char resource[1024];                 /* Printer resource */
+
+
+  snprintf(resource, sizeof(resource), "/printers/%s", name);
+
+  ippDelete(cupsGetResponse(http, resource));
+
+  return (cupsLastError());
 }
 
 
@@ -159,18 +277,19 @@ void
 cupsFreeJobs(int        num_jobs,      /* I - Number of jobs */
              cups_job_t *jobs)         /* I - Jobs */
 {
-  int  i;                              /* Looping var */
+  int          i;                      /* Looping var */
+  cups_job_t   *job;                   /* Current job */
 
 
-  if (num_jobs <= 0 || jobs == NULL)
+  if (num_jobs <= 0 || !jobs)
     return;
 
-  for (i = 0; i < num_jobs; i ++)
+  for (i = num_jobs, job = jobs; i > 0; i --, job ++)
   {
-    free(jobs[i].dest);
-    free(jobs[i].user);
-    free(jobs[i].format);
-    free(jobs[i].title);
+    _cupsStrFree(job->dest);
+    _cupsStrFree(job->user);
+    _cupsStrFree(job->format);
+    _cupsStrFree(job->title);
   }
 
   free(jobs);
@@ -193,26 +312,20 @@ cupsGetClasses(char ***classes)           /* O - Classes */
                *response;              /* IPP Response */
   ipp_attribute_t *attr;               /* Current attribute */
   char         **temp;                 /* Temporary pointer */
-  _cups_globals_t *cg = _cupsGlobals();        /* Pointer to library globals */
+  http_t       *http;                  /* Connection to server */
 
 
-  if (classes == NULL)
+  if (!classes)
   {
     _cupsSetError(IPP_INTERNAL_ERROR, NULL);
 
     return (0);
   }
 
- /*
-  * Try to connect to the server...
-  */
-
-  if (!cups_connect("default", NULL, NULL))
-  {
-    DEBUG_puts("Unable to connect to server!");
+  *classes = NULL;
 
+  if ((http = _cupsConnect()) == NULL)
     return (0);
-  }
 
  /*
   * Build a CUPS_GET_CLASSES request, which requires the following
@@ -232,10 +345,9 @@ cupsGetClasses(char ***classes)            /* O - Classes */
   * Do the request and get back a response...
   */
 
-  n        = 0;
-  *classes = NULL;
+  n = 0;
 
-  if ((response = cupsDoRequest(cg->http, request, "/")) != NULL)
+  if ((response = cupsDoRequest(http, request, "/")) != NULL)
   {
     for (attr = response->attrs; attr != NULL; attr = attr->next)
       if (attr->name != NULL &&
@@ -290,38 +402,11 @@ cupsGetClasses(char ***classes)           /* O - Classes */
 const char *                           /* O - Default printer or NULL */
 cupsGetDefault(void)
 {
-  const char   *var;                   /* Environment variable */
-  _cups_globals_t *cg = _cupsGlobals();        /* Pointer to library globals */
-
-
- /*
-  * First see if the LPDEST or PRINTER environment variables are
-  * set...  However, if PRINTER is set to "lp", ignore it to work
-  * around a "feature" in most Linux distributions - the default
-  * user login scripts set PRINTER to "lp"...
-  */
-
-  if ((var = getenv("LPDEST")) != NULL)
-    return (var);
-  else if ((var = getenv("PRINTER")) != NULL && strcmp(var, "lp") != 0)
-    return (var);
-
- /*
-  * Try to connect to the server...
-  */
-
-  if (!cups_connect("default", NULL, NULL))
-  {
-    DEBUG_puts("Unable to connect to server!");
-
-    return (NULL);
-  }
-
  /*
   * Return the default printer...
   */
 
-  return (cupsGetDefault2(cg->http));
+  return (cupsGetDefault2(CUPS_HTTP_DEFAULT));
 }
 
 
@@ -361,11 +446,12 @@ cupsGetDefault2(http_t *http)             /* I - HTTP connection */
     return (var);
 
  /*
-  * Range check input...
+  * Connect to the server as needed...
   */
 
   if (!http)
-    return (NULL);
+    if ((http = _cupsConnect()) == NULL)
+      return (NULL);
 
  /*
   * Build a CUPS_GET_DEFAULT request, which requires the following
@@ -383,9 +469,11 @@ cupsGetDefault2(http_t *http)              /* I - HTTP connection */
 
   if ((response = cupsDoRequest(http, request, "/")) != NULL)
   {
-    if ((attr = ippFindAttribute(response, "printer-name", IPP_TAG_NAME)) != NULL)
+    if ((attr = ippFindAttribute(response, "printer-name",
+                                 IPP_TAG_NAME)) != NULL)
     {
-      strlcpy(cg->def_printer, attr->values[0].string.text, sizeof(cg->def_printer));
+      strlcpy(cg->def_printer, attr->values[0].string.text,
+              sizeof(cg->def_printer));
       ippDelete(response);
       return (cg->def_printer);
     }
@@ -409,24 +497,11 @@ cupsGetJobs(cups_job_t **jobs,            /* O - Job data */
            int        completed)       /* I - -1 = show all, 0 = active, *
                                         *     1 = completed jobs         */
 {
-  _cups_globals_t *cg = _cupsGlobals();        /* Pointer to library globals */
-
- /*
-  * Try to connect to the server...
-  */
-
-  if (!cups_connect("default", NULL, NULL))
-  {
-    DEBUG_puts("Unable to connect to server!");
-
-    return (-1);
-  }
-
  /*
   * Return the jobs...
   */
 
-  return (cupsGetJobs2(cg->http, jobs, mydest, myjobs, completed));
+  return (cupsGetJobs2(CUPS_HTTP_DEFAULT, jobs, mydest, myjobs, completed));
 }
 
 
@@ -438,7 +513,7 @@ cupsGetJobs(cups_job_t **jobs,              /* O - Job data */
  */
 
 int                                    /* O - Number of jobs */
-cupsGetJobs2(http_t     *http,         /* I - HTTP connection */
+cupsGetJobs2(http_t     *http,         /* I - HTTP connection or CUPS_HTTP_DEFAULT */
              cups_job_t **jobs,                /* O - Job data */
              const char *mydest,       /* I - NULL = all destinations,       *
                                         *     otherwise show jobs for mydest */
@@ -484,7 +559,7 @@ cupsGetJobs2(http_t     *http,              /* I - HTTP connection */
   * Range check input...
   */
 
-  if (!http || !jobs)
+  if (!jobs)
   {
     _cupsSetError(IPP_INTERNAL_ERROR, NULL);
 
@@ -508,6 +583,9 @@ cupsGetJobs2(http_t     *http,              /* I - HTTP connection */
   else
     strcpy(uri, "ipp://localhost/jobs");
 
+  if (!http)
+    if ((http = _cupsConnect()) == NULL)
+      return (-1);
 
  /*
   * Build an IPP_GET_JOBS request, which requires the following
@@ -553,16 +631,16 @@ cupsGetJobs2(http_t     *http,            /* I - HTTP connection */
 
   if ((response = cupsDoRequest(http, request, "/")) != NULL)
   {
-    for (attr = response->attrs; attr != NULL; attr = attr->next)
+    for (attr = response->attrs; attr; attr = attr->next)
     {
      /*
       * Skip leading attributes until we hit a job...
       */
 
-      while (attr != NULL && attr->group_tag != IPP_TAG_JOB)
+      while (attr && attr->group_tag != IPP_TAG_JOB)
         attr = attr->next;
 
-      if (attr == NULL)
+      if (!attr)
         break;
 
      /*
@@ -581,42 +659,42 @@ cupsGetJobs2(http_t     *http,            /* I - HTTP connection */
       completed_time  = 0;
       processing_time = 0;
 
-      while (attr != NULL && attr->group_tag == IPP_TAG_JOB)
+      while (attr && attr->group_tag == IPP_TAG_JOB)
       {
-        if (strcmp(attr->name, "job-id") == 0 &&
+        if (!strcmp(attr->name, "job-id") &&
            attr->value_tag == IPP_TAG_INTEGER)
          id = attr->values[0].integer;
-        else if (strcmp(attr->name, "job-state") == 0 &&
+        else if (!strcmp(attr->name, "job-state") &&
                 attr->value_tag == IPP_TAG_ENUM)
          state = (ipp_jstate_t)attr->values[0].integer;
-        else if (strcmp(attr->name, "job-priority") == 0 &&
+        else if (!strcmp(attr->name, "job-priority") &&
                 attr->value_tag == IPP_TAG_INTEGER)
          priority = attr->values[0].integer;
-        else if (strcmp(attr->name, "job-k-octets") == 0 &&
+        else if (!strcmp(attr->name, "job-k-octets") &&
                 attr->value_tag == IPP_TAG_INTEGER)
          size = attr->values[0].integer;
-        else if (strcmp(attr->name, "time-at-completed") == 0 &&
+        else if (!strcmp(attr->name, "time-at-completed") &&
                 attr->value_tag == IPP_TAG_INTEGER)
          completed_time = attr->values[0].integer;
-        else if (strcmp(attr->name, "time-at-creation") == 0 &&
+        else if (!strcmp(attr->name, "time-at-creation") &&
                 attr->value_tag == IPP_TAG_INTEGER)
          creation_time = attr->values[0].integer;
-        else if (strcmp(attr->name, "time-at-processing") == 0 &&
+        else if (!strcmp(attr->name, "time-at-processing") &&
                 attr->value_tag == IPP_TAG_INTEGER)
          processing_time = attr->values[0].integer;
-        else if (strcmp(attr->name, "job-printer-uri") == 0 &&
+        else if (!strcmp(attr->name, "job-printer-uri") &&
                 attr->value_tag == IPP_TAG_URI)
        {
          if ((dest = strrchr(attr->values[0].string.text, '/')) != NULL)
            dest ++;
         }
-        else if (strcmp(attr->name, "job-originating-user-name") == 0 &&
+        else if (!strcmp(attr->name, "job-originating-user-name") &&
                 attr->value_tag == IPP_TAG_NAME)
          user = attr->values[0].string.text;
-        else if (strcmp(attr->name, "document-format") == 0 &&
+        else if (!strcmp(attr->name, "document-format") &&
                 attr->value_tag == IPP_TAG_MIMETYPE)
          format = attr->values[0].string.text;
-        else if (strcmp(attr->name, "job-name") == 0 &&
+        else if (!strcmp(attr->name, "job-name") &&
                 (attr->value_tag == IPP_TAG_TEXT ||
                  attr->value_tag == IPP_TAG_NAME))
          title = attr->values[0].string.text;
@@ -628,9 +706,9 @@ cupsGetJobs2(http_t     *http,              /* I - HTTP connection */
       * See if we have everything needed...
       */
 
-      if (dest == NULL || id == 0)
+      if (!dest || !id)
       {
-        if (attr == NULL)
+        if (!attr)
          break;
        else
           continue;
@@ -645,17 +723,20 @@ cupsGetJobs2(http_t     *http,            /* I - HTTP connection */
       else
        temp = realloc(*jobs, sizeof(cups_job_t) * (n + 1));
 
-      if (temp == NULL)
+      if (!temp)
       {
        /*
         * Ran out of memory!
         */
 
+        _cupsSetError(IPP_INTERNAL_ERROR, strerror(errno));
+
        cupsFreeJobs(n, *jobs);
        *jobs = NULL;
 
         ippDelete(response);
-       return (0);
+
+       return (-1);
       }
 
       *jobs = temp;
@@ -666,10 +747,10 @@ cupsGetJobs2(http_t     *http,            /* I - HTTP connection */
       * Copy the data over...
       */
 
-      temp->dest            = strdup(dest);
-      temp->user            = strdup(user);
-      temp->format          = strdup(format);
-      temp->title           = strdup(title);
+      temp->dest            = _cupsStrAlloc(dest);
+      temp->user            = _cupsStrAlloc(user);
+      temp->format          = _cupsStrAlloc(format);
+      temp->title           = _cupsStrAlloc(title);
       temp->id              = id;
       temp->priority        = priority;
       temp->state           = state;
@@ -678,7 +759,7 @@ cupsGetJobs2(http_t     *http,              /* I - HTTP connection */
       temp->creation_time   = creation_time;
       temp->processing_time = processing_time;
 
-      if (attr == NULL)
+      if (!attr)
         break;
     }
 
@@ -706,24 +787,13 @@ cupsGetPPD(const char *name)              /* I - Printer name */
   time_t       modtime = 0;            /* Modification time */
 
 
- /*
-  * See if we can connect to the server...
-  */
-
-  if (!cups_connect(name, NULL, NULL))
-  {
-    DEBUG_puts("Unable to connect to server!");
-
-    return (NULL);
-  }
-
  /*
   * Return the PPD file...
   */
 
   cg->ppd_filename[0] = '\0';
 
-  if (cupsGetPPD3(cg->http, name, &modtime, cg->ppd_filename,
+  if (cupsGetPPD3(CUPS_HTTP_DEFAULT, name, &modtime, cg->ppd_filename,
                   sizeof(cg->ppd_filename)) == HTTP_OK)
     return (cg->ppd_filename);
   else
@@ -741,7 +811,7 @@ cupsGetPPD(const char *name)                /* I - Printer name */
  */
 
 const char *                           /* O - Filename for PPD file */
-cupsGetPPD2(http_t     *http,          /* I - HTTP connection */
+cupsGetPPD2(http_t     *http,          /* I - HTTP connection or CUPS_HTTP_DEFAULT */
             const char *name)          /* I - Printer name */
 {
   _cups_globals_t *cg = _cupsGlobals();        /* Pointer to library globals */
@@ -775,7 +845,7 @@ cupsGetPPD2(http_t     *http,               /* I - HTTP connection */
  */
 
 http_status_t                          /* O  - HTTP status */
-cupsGetPPD3(http_t     *http,          /* I  - HTTP connection */
+cupsGetPPD3(http_t     *http,          /* I  - HTTP connection or CUPS_HTTP_DEFAULT */
             const char *name,          /* I  - Printer name */
            time_t     *modtime,        /* IO - Modification time */
            char       *buffer,         /* I  - Filename buffer */
@@ -802,12 +872,6 @@ cupsGetPPD3(http_t     *http,              /* I  - HTTP connection */
                 "bufsize=%d)\n", http, name ? name : "(null)", modtime,
                modtime ? *modtime : 0, buffer, (int)bufsize));
 
-  if (!http)
-  {
-    _cupsSetError(IPP_INTERNAL_ERROR, "No HTTP connection!");
-    return (HTTP_NOT_ACCEPTABLE);
-  }
-
   if (!name)
   {
     _cupsSetError(IPP_INTERNAL_ERROR, "No printer name!");
@@ -830,6 +894,9 @@ cupsGetPPD3(http_t     *http,               /* I  - HTTP connection */
   * Try finding a printer URI for this printer...
   */
 
+  if (!http)
+    http = _cupsConnect();
+
   if (!cups_get_printer_uri(http, name, hostname, sizeof(hostname), &port,
                             resource, sizeof(resource), 0))
     return (HTTP_NOT_FOUND);
@@ -972,26 +1039,28 @@ cupsGetPrinters(char ***printers)        /* O - Printers */
                *response;              /* IPP Response */
   ipp_attribute_t *attr;               /* Current attribute */
   char         **temp;                 /* Temporary pointer */
-  _cups_globals_t *cg = _cupsGlobals();        /* Pointer to library globals */
+  http_t       *http;                  /* Connection to server */
+
 
+ /*
+  * Range check input...
+  */
 
-  if (printers == NULL)
+  if (!printers)
   {
     _cupsSetError(IPP_INTERNAL_ERROR, NULL);
 
     return (0);
   }
 
+  *printers = NULL;
+
  /*
   * Try to connect to the server...
   */
 
-  if (!cups_connect("default", NULL, NULL))
-  {
-    DEBUG_puts("Unable to connect to server!");
-
+  if ((http = _cupsConnect()) == NULL)
     return (0);
-  }
 
  /*
   * Build a CUPS_GET_PRINTERS request, which requires the following
@@ -1017,10 +1086,9 @@ cupsGetPrinters(char ***printers)        /* O - Printers */
   * Do the request and get back a response...
   */
 
-  n         = 0;
-  *printers = NULL;
+  n = 0;
 
-  if ((response = cupsDoRequest(cg->http, request, "/")) != NULL)
+  if ((response = cupsDoRequest(http, request, "/")) != NULL)
   {
     for (attr = response->attrs; attr != NULL; attr = attr->next)
       if (attr->name != NULL &&
@@ -1077,7 +1145,7 @@ cupsGetPrinters(char ***printers) /* O - Printers */
  */
 
 char *                                 /* O - Name of PPD file or NULL on error */
-cupsGetServerPPD(http_t     *http,     /* I - HTTP connection */
+cupsGetServerPPD(http_t     *http,     /* I - HTTP connection or CUPS_HTTP_DEFAULT */
                  const char *name)     /* I - Name of PPD file ("ppd-name") */
 {
   int                  fd;             /* PPD file descriptor */
@@ -1090,16 +1158,17 @@ cupsGetServerPPD(http_t     *http,      /* I - HTTP connection */
   * Range check input...
   */
 
-  if (!http || !name)
+  if (!name)
   {
-    if (!http)
-      _cupsSetError(IPP_INTERNAL_ERROR, "No HTTP connection!");
-    else
-      _cupsSetError(IPP_INTERNAL_ERROR, "No PPD name!");
+    _cupsSetError(IPP_INTERNAL_ERROR, "No PPD name!");
 
     return (NULL);
   }
 
+  if (!http)
+    if ((http = _cupsConnect()) == NULL)
+      return (NULL);
+
  /*
   * Get a temp file...
   */
@@ -1176,7 +1245,8 @@ cupsPrintFile(const char    *name,        /* I - Printer or class name */
                 "title=\"%s\", num_options=%d, options=%p)\n",
                 name, filename, title, num_options, options));
 
-  return (cupsPrintFiles(name, 1, &filename, title, num_options, options));
+  return (cupsPrintFiles2(CUPS_HTTP_DEFAULT, name, 1, &filename, title,
+                          num_options, options));
 }
 
 
@@ -1187,19 +1257,20 @@ cupsPrintFile(const char    *name,      /* I - Printer or class name */
  */
 
 int                                    /* O - Job ID */
-cupsPrintFile2(http_t        *http,    /* I - HTTP connection */
-               const char    *name,    /* I - Printer or class name */
-               const char    *filename,        /* I - File to print */
-              const char    *title,    /* I - Title of job */
-               int           num_options,
-                                       /* I - Number of options */
-              cups_option_t *options)  /* I - Options */
+cupsPrintFile2(
+    http_t        *http,               /* I - HTTP connection */
+    const char    *name,               /* I - Printer or class name */
+    const char    *filename,           /* I - File to print */
+    const char    *title,              /* I - Title of job */
+    int           num_options,         /* I - Number of options */
+    cups_option_t *options)            /* I - Options */
 {
   DEBUG_printf(("cupsPrintFile2(http=%p, name=\"%s\", filename=\"%s\", "
                 "title=\"%s\", num_options=%d, options=%p)\n",
                 http, name, filename, title, num_options, options));
 
-  return (cupsPrintFiles2(http, name, 1, &filename, title, num_options, options));
+  return (cupsPrintFiles2(http, name, 1, &filename, title, num_options,
+                          options));
 }
 
 
@@ -1209,44 +1280,28 @@ cupsPrintFile2(http_t        *http,     /* I - HTTP connection */
  */
 
 int                                    /* O - Job ID */
-cupsPrintFiles(const char    *name,    /* I - Printer or class name */
-               int           num_files,        /* I - Number of files */
-               const char    **files,  /* I - File(s) to print */
-              const char    *title,    /* I - Title of job */
-               int           num_options,
-                                       /* I - Number of options */
-              cups_option_t *options)  /* I - Options */
+cupsPrintFiles(
+    const char    *name,               /* I - Printer or class name */
+    int           num_files,           /* I - Number of files */
+    const char    **files,             /* I - File(s) to print */
+    const char    *title,              /* I - Title of job */
+    int           num_options,         /* I - Number of options */
+    cups_option_t *options)            /* I - Options */
 {
-  _cups_globals_t *cg = _cupsGlobals();        /* Pointer to library globals */
-
   DEBUG_printf(("cupsPrintFiles(name=\"%s\", num_files=%d, "
                 "files=%p, title=\"%s\", num_options=%d, options=%p)\n",
                 name, num_files, files, title, num_options, options));
 
 
- /*
-  * Setup a connection and request data...
-  */
-
-  if (!cups_connect(name, NULL, NULL))
-  {
-    DEBUG_printf(("cupsPrintFiles: Unable to open connection - %s.\n",
-                  strerror(errno)));
-    DEBUG_puts("Unable to connect to server!");
-
-    return (0);
-  }
-
  /*
   * Print the file(s)...
   */
 
-  return (cupsPrintFiles2(cg->http, name, num_files, files, title,
+  return (cupsPrintFiles2(CUPS_HTTP_DEFAULT, name, num_files, files, title,
                           num_options, options));
 }
 
 
-
 /*
  * 'cupsPrintFiles2()' - Print one or more files to a printer or class on the
  *                       specified server.
@@ -1255,26 +1310,26 @@ cupsPrintFiles(const char    *name,     /* I - Printer or class name */
  */
 
 int                                    /* O - Job ID */
-cupsPrintFiles2(http_t        *http,   /* I - HTTP connection */
-                const char    *name,   /* I - Printer or class name */
-                int           num_files,/* I - Number of files */
-                const char    **files, /* I - File(s) to print */
-               const char    *title,   /* I - Title of job */
-                int           num_options,
-                                       /* I - Number of options */
-               cups_option_t *options) /* I - Options */
+cupsPrintFiles2(
+    http_t        *http,               /* I - HTTP connection or CUPS_HTTP_DEFAULT */
+    const char    *name,               /* I - Printer or class name */
+    int           num_files,           /* I - Number of files */
+    const char    **files,             /* I - File(s) to print */
+    const char    *title,              /* I - Title of job */
+    int           num_options,         /* I - Number of options */
+    cups_option_t *options)            /* I - Options */
 {
   int          i;                      /* Looping var */
-  const char   *val;                   /* Pointer to option value */
-  ipp_t                *request;               /* IPP request */
-  ipp_t                *response;              /* IPP response */
-  ipp_attribute_t *attr;               /* IPP job-id attribute */
-  char         uri[HTTP_MAX_URI];      /* Printer URI */
-  int          jobid;                  /* New job ID */
-  const char   *base;                  /* Basename of current filename */
+  int          job_id;                 /* New job ID */
+  const char   *docname;               /* Basename of current filename */
+  const char   *format;                /* Document format */
+  cups_file_t  *fp;                    /* Current file */
+  char         buffer[8192];           /* Copy buffer */
+  ssize_t      bytes;                  /* Bytes in buffer */
+  http_status_t        status;                 /* Status of write */
 
 
-  DEBUG_printf(("cupsPrintFiles(http=%p, name=\"%s\", num_files=%d, "
+  DEBUG_printf(("cupsPrintFiles2(http=%p, name=\"%s\", num_files=%d, "
                 "files=%p, title=\"%s\", num_options=%d, options=%p)\n",
                 http, name, num_files, files, title, num_options, options));
 
@@ -1282,7 +1337,7 @@ cupsPrintFiles2(http_t        *http,      /* I - HTTP connection */
   * Range check input...
   */
 
-  if (!http || !name || num_files < 1 || files == NULL)
+  if (!name || num_files < 1 || !files)
   {
     _cupsSetError(IPP_INTERNAL_ERROR, NULL);
 
@@ -1290,215 +1345,204 @@ cupsPrintFiles2(http_t        *http,  /* I - HTTP connection */
   }
 
  /*
-  * Setup the printer URI...
+  * Create the print job...
   */
 
-  if (httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
-                       "localhost", 0, "/printers/%s", name) != HTTP_URI_OK)
-  {
-    _cupsSetError(IPP_INTERNAL_ERROR, NULL);
-
+  if ((job_id = cupsCreateJob(http, name, title, num_options, options)) == 0)
     return (0);
-  }
 
  /*
-  * Build a standard CUPS URI for the printer and fill the standard IPP
-  * attributes...
+  * Send each of the files...
   */
 
-  if ((request = ippNewRequest(num_files == 1 ? IPP_PRINT_JOB :
-                                                IPP_CREATE_JOB)) == NULL)
-  {
-    _cupsSetError(IPP_INTERNAL_ERROR, NULL);
-
-    return (0);
-  }
-
-  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
-               NULL, uri);
-
-  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
-               NULL, cupsUser());
+  if (cupsGetOption("raw", num_options, options))
+    format = CUPS_FORMAT_RAW;
+  else if ((format = cupsGetOption("document-format", num_options,
+                                  options)) == NULL)
+    format = CUPS_FORMAT_AUTO;
 
-  if (title)
-    ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "job-name", NULL,
-                 title);
-
- /*
-  * Then add all options...
-  */
-
-  cupsEncodeOptions(request, num_options, options);
-
- /*
-  * Do the request...
-  */
-
-  snprintf(uri, sizeof(uri), "/printers/%s", name);
+  for (i = 0; i < num_files; i ++)
+  {
+   /*
+    * Start the next file...
+    */
 
-  if (num_files == 1)
-    response = cupsDoFileRequest(http, request, uri, *files);
-  else
-    response = cupsDoRequest(http, request, uri);
+    if ((docname = strrchr(files[i], '/')) != NULL)
+      docname ++;
+    else
+      docname = files[i];
 
-  if (response == NULL)
-    jobid = 0;
-  else if (response->request.status.status_code > IPP_OK_CONFLICT)
-  {
-    DEBUG_printf(("IPP response code was 0x%x!\n",
-                  response->request.status.status_code));
-    jobid = 0;
-  }
-  else if ((attr = ippFindAttribute(response, "job-id", IPP_TAG_INTEGER)) == NULL)
-  {
-    DEBUG_puts("No job ID!");
+    if ((fp = cupsFileOpen(files[i], "rb")) == NULL)
+    {
+     /*
+      * Unable to open print file, cancel the job and return...
+      */
 
-    _cupsSetError(IPP_INTERNAL_ERROR, NULL);
+      cupsCancelJob2(http, job_id, 0);
+      return (0);
+    }
 
-    jobid = 0;
-  }
-  else
-    jobid = attr->values[0].integer;
+    status = cupsStartDocument(http, name, job_id, docname, format,
+                               i == (num_files - 1));
 
-  if (response != NULL)
-    ippDelete(response);
+    while (status == HTTP_CONTINUE &&
+           (bytes = cupsFileRead(fp, buffer, sizeof(buffer))) > 0)
+      status = cupsWriteRequestData(http, buffer, bytes);
 
- /*
-  * Handle multiple file jobs if the create-job operation worked...
-  */
+    cupsFileClose(fp);
 
-  if (jobid > 0 && num_files > 1)
-    for (i = 0; i < num_files; i ++)
+    if (status != HTTP_CONTINUE || cupsFinishDocument(http, name) != IPP_OK)
     {
      /*
-      * Build a standard CUPS URI for the job and fill the standard IPP
-      * attributes...
+      * Unable to queue, cancel the job and return...
       */
 
-      if ((request = ippNewRequest(IPP_SEND_DOCUMENT)) == NULL)
-       return (0);
-
-      snprintf(uri, sizeof(uri), "ipp://localhost/jobs/%d", jobid);
+      cupsCancelJob2(http, job_id, 0);
+      return (0);
+    }
+  }
 
-      ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri",
-                  NULL, uri);
+  return (job_id);
+}
 
-     /*
-      * Handle raw print files...
-      */
 
-      if (cupsGetOption("raw", num_options, options))
-       ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_MIMETYPE,
-                    "document-format", NULL, "application/vnd.cups-raw");
-      else if ((val = cupsGetOption("document-format", num_options,
-                                    options)) != NULL)
-       ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_MIMETYPE,
-                    "document-format", NULL, val);
-      else
-       ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_MIMETYPE,
-                    "document-format", NULL, "application/octet-stream");
+/*
+ * 'cupsStartDocument()' - Add a document to a job created with cupsCreateJob().
+ *
+ * Use cupsWriteRequestData() to write data for the document and
+ * cupsFinishDocument() to finish the document and get the submission status.
+ *
+ * The MIME type constants CUPS_FORMAT_AUTO, CUPS_FORMAT_PDF,
+ * CUPS_FORMAT_POSTSCRIPT, CUPS_FORMAT_RAW, and CUPS_FORMAT_TEXT are provided
+ * for the "format" argument, although any supported MIME type string can be
+ * supplied.
+ *
+ * @since CUPS 1.4@
+ */
 
-      ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
-                   "requesting-user-name", NULL, cupsUser());
+http_status_t                          /* O - HTTP status of request */
+cupsStartDocument(
+    http_t     *http,                  /* I - HTTP connection or CUPS_HTTP_DEFAULT */
+    const char *name,                  /* I - Printer or class name */
+    int        job_id,                 /* I - Job ID from cupsCreateJob() */
+    const char *docname,               /* I - Name of document */
+    const char *format,                        /* I - MIME type or CUPS_FORMAT_foo */
+    int        last_document)          /* I - 1 for last document in job, 0 otherwise */
+{
+  char         resource[1024],         /* Resource for destinatio */
+               printer_uri[1024];      /* Printer URI */
+  ipp_t                *request;               /* Send-Document request */
+  http_status_t        status;                 /* HTTP status */
 
-     /*
-      * Add the original document filename...
-      */
 
-      if ((base = strrchr(files[i], '/')) != NULL)
-        base ++;
-      else
-        base = files[i];
+ /*
+  * Create a Send-Document request...
+  */
 
-      ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "document-name",
-                   NULL, base);
+  if ((request = ippNewRequest(IPP_SEND_DOCUMENT)) == NULL)
+  {
+    _cupsSetError(IPP_INTERNAL_ERROR, NULL);
+    return (0);
+  }
 
-     /*
-      * Is this the last document?
-      */
+  httpAssembleURIf(HTTP_URI_CODING_ALL, printer_uri, sizeof(printer_uri), "ipp",
+                   NULL, "localhost", ippPort(), "/printers/%s", name);
+  snprintf(resource, sizeof(resource), "/printers/%s", name);
 
-      if (i == (num_files - 1))
-        ippAddBoolean(request, IPP_TAG_OPERATION, "last-document", 1);
+  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
+               NULL, printer_uri);
+  ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_INTEGER, "job-id", job_id);
+  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
+               NULL, cupsUser());
+  if (docname)
+    ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "document-name",
+                 NULL, docname);
+  if (format)
+    ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_MIMETYPE,
+                 "document-format", NULL, format);
+  ippAddBoolean(request, IPP_TAG_OPERATION, "last-document", last_document);
 
    /*
-      * Send the file...
-      */
+ /*
+  * Send and delete the request, then return the status...
+  */
 
-      snprintf(uri, sizeof(uri), "/printers/%s", name);
+  status = cupsSendRequest(http, request, resource, CUPS_LENGTH_VARIABLE);
 
-      if ((response = cupsDoFileRequest(http, request, uri,
-                                        files[i])) != NULL)
-       ippDelete(response);
-    }
+  ippDelete(request);
 
-  return (jobid);
+  return (status);
 }
 
 
 /*
- * 'cups_connect()' - Connect to the specified host...
+ * '_cupsConnect()' - Get the default server connection...
  */
 
-static char *                          /* I - Printer name or NULL */
-cups_connect(const char *name,         /* I - Destination (printer[@host]) */
-            char       *printer,       /* O - Printer name [HTTP_MAX_URI] */
-             char       *hostname)     /* O - Hostname [HTTP_MAX_URI] */
+http_t *                               /* O - HTTP connection */
+_cupsConnect(void)
 {
-  char hostbuf[HTTP_MAX_URI],          /* Name of host */
-       http_hostname[HTTP_MAX_HOST];   /* Hostname associated with connection */
-  _cups_globals_t  *cg = _cupsGlobals();/* Pointer to library globals */
-
-
-  DEBUG_printf(("cups_connect(\"%s\", %p, %p)\n", name, printer, hostname));
-
-  if (name == NULL)
-  {
-    _cupsSetError(IPP_BAD_REQUEST, NULL);
+  _cups_globals_t *cg = _cupsGlobals();        /* Pointer to library globals */
 
-    return (NULL);
-  }
 
  /*
-  * All jobs are now queued to cupsServer() to avoid hostname
-  * resolution problems and to ensure that the user sees all
-  * locally queued jobs locally.
+  * See if we are connected to the same server...
   */
 
-  strlcpy(hostbuf, cupsServer(), sizeof(hostbuf));
+  if (cg->http)
+  {
+    int        port;                           /* Port for connection */
 
-  httpGetHostname(cg->http, http_hostname, sizeof(http_hostname));
 
-  if (hostname != NULL)
-    strlcpy(hostname, hostbuf, HTTP_MAX_URI);
-  else
-    hostname = hostbuf;
+   /*
+    * Get the port associated with the current connection...
+    */
 
-  if (printer != NULL)
-    strlcpy(printer, name, HTTP_MAX_URI);
-  else
-    printer = (char *)name;
+#ifdef AF_INET6
+    if (cg->http->hostaddr->addr.sa_family == AF_INET6)
+      port = ntohs(cg->http->hostaddr->ipv6.sin6_port);
+    else
+#endif /* AF_INET6 */
+    if (cg->http->hostaddr->addr.sa_family == AF_INET)
+      port = ntohs(cg->http->hostaddr->ipv4.sin_port);
+    else
+      port = cg->ipp_port;
 
-  if (cg->http != NULL)
-  {
-    if (!strcasecmp(http_hostname, hostname))
-      return (printer);
+   /*
+    * Compare the connection hostname, port, and encryption settings to
+    * the cached defaults; these were initialized the first time we
+    * connected...
+    */
+
+    if (strcmp(cg->http->hostname, cg->server) || cg->ipp_port != port ||
+        (cg->http->encryption != cg->encryption &&
+        cg->http->encryption == HTTP_ENCRYPT_NEVER))
+    {
+     /*
+      * Need to close the current connection because something has changed...
+      */
 
-    httpClose(cg->http);
+      httpClose(cg->http);
+      cg->http = NULL;
+    }
   }
 
-  DEBUG_printf(("connecting to %s on port %d...\n", hostname, ippPort()));
+ /*
+  * (Re)connect as needed...
+  */
 
-  if ((cg->http = httpConnectEncrypt(hostname, ippPort(),
-                                     cupsEncryption())) == NULL)
+  if (!cg->http)
   {
-    DEBUG_puts("Unable to connect to server!");
+    if ((cg->http = httpConnectEncrypt(cupsServer(), ippPort(),
+                                       cupsEncryption())) == NULL)
+      _cupsSetError(IPP_SERVICE_UNAVAILABLE,
+                    errno ? strerror(errno) : "Unable to connect to host.");
+  }
 
-    _cupsSetError(IPP_SERVICE_UNAVAILABLE, strerror(errno));
+ /*
+  * Return the cached connection...
+  */
 
-    return (NULL);
-  }
-  else
-    return (printer);
+  return (cg->http);
 }
 
 
index ead73978a552db738e339949b8cca7722641305f..72f5da9eee28e5a95dce654c780f1021b30d4056 100644 (file)
@@ -14,7 +14,7 @@
 %
 %   PostScript test page for the Common UNIX Printing System ("CUPS").
 %
-%   Copyright 2007 Apple Inc.
+%   Copyright 2007-2008 Apple Inc.
 %   Copyright 1993-2007 Easy Software Products
 %
 %   These coded instructions, statements, and computer programs are the
@@ -567,16 +567,16 @@ gsave
   pageWidth 17 mul                     % Center of page
   pageHeight 10 mul                    % Bottom of page
   moveto                               % Position text
-  (Printed Using CUPS v1.3.x) show
+  (Printed Using CUPS v1.4.x) show
 
   pageWidth 17 mul                     % Left side of page
   pageHeight 8 mul                     % Move down...
   2 copy moveto                                % Position text
   smallFont setfont                    % Font
-  (Copyright 2007 Apple Inc., All Rights Reserved. CUPS and the CUPS logo are the trademark) show
+  (Copyright 2007-2008 Apple Inc., All Rights Reserved. CUPS and the CUPS logo are the) show
   pageHeight 2 add sub                 % Move down...
   2 copy moveto                                % Position text
-  (property of Apple Inc., 1 Infinite Loop, Cupertino, CA 95014, USA.) show
+  (trademark property of Apple Inc., 1 Infinite Loop, Cupertino, CA 95014, USA.) show
   pageHeight 2 mul 4 add sub           % Move down...
   moveto                               % Position text
   (Need help? Contact your operating system vendor or visit "http://www.cups.org/".) show
index fa40ee272df04cf54e7bf365078fc5f310b646f4..560f7668bad6ddd5eccc82dd7855e795f7d3500a 100644 (file)
@@ -77,8 +77,8 @@ assistance:</P>
 <TR><TD>&nbsp;</TD></TR>
 <TR><TD CLASS="trailer">The Common UNIX Printing System, CUPS, and
 the CUPS logo are the trademark property of
-<A HREF="http://www.apple.com">Apple Inc.</A> CUPS is copyright 2007 by Apple
-Inc., all rights reserved.</TD></TR>
+<A HREF="http://www.apple.com">Apple Inc.</A> CUPS is copyright 2007-2008 by
+Apple Inc., all rights reserved.</TD></TR>
 </TABLE>
 </BODY>
 </HTML>
index ef2db81ad9d0fb4c7eeb3124f6ef239c0731c732..68ce70c472004d5287f254ca2f6676fedcd73e4d 100644 (file)
@@ -3,7 +3,7 @@
 .\"
 .\"   cupsd.conf man page for the Common UNIX Printing System (CUPS).
 .\"
-.\"   Copyright 2007 by Apple Inc.
+.\"   Copyright 2007-2008 by Apple Inc.
 .\"   Copyright 1997-2006 by Easy Software Products.
 .\"
 .\"   These coded instructions, statements, and computer programs are the
@@ -12,7 +12,7 @@
 .\"   which should have been included with this file.  If this file is
 .\"   file is missing or damaged, see the license at "http://www.cups.org/".
 .\"
-.TH cupsd.conf 5 "Common UNIX Printing System" "6 June 2006" "Apple Inc."
+.TH cupsd.conf 5 "Common UNIX Printing System" "2 January 2008" "Apple Inc."
 .SH NAME
 cupsd.conf \- server configuration file for cups
 .SH DESCRIPTION
@@ -230,6 +230,12 @@ DefaultPolicy policy-name
 .br
 Specifies the default access policy to use.
 .TP 5
+DefaultShared Yes
+.TP 5
+DefaultShared No
+.br
+Specifies whether local printers are shared by default.
+.TP 5
 Deny all
 .TP 5
 Deny none
@@ -606,7 +612,7 @@ Specifies the user name or ID that is used when running external programs.
 .br
 http://localhost:631/help
 .SH COPYRIGHT
-Copyright 2007 by Apple Inc.
+Copyright 2007-2008 by Apple Inc.
 .\"
 .\" End of "$Id: cupsd.conf.man.in 7002 2007-10-01 23:07:37Z mike $".
 .\"
index 7b7f5b4a99ed722c88e52294ee57362e156c5132..ab6fc264ee599dcbcc3032a908fa5c7490c44d51 100644 (file)
@@ -3,7 +3,7 @@
 .\"
 .\"   lpadmin man page for the Common UNIX Printing System (CUPS).
 .\"
-.\"   Copyright 2007 by Apple Inc.
+.\"   Copyright 2007-2008 by Apple Inc.
 .\"   Copyright 1997-2006 by Easy Software Products.
 .\"
 .\"   These coded instructions, statements, and computer programs are the
@@ -12,7 +12,7 @@
 .\"   which should have been included with this file.  If this file is
 .\"   file is missing or damaged, see the license at "http://www.cups.org/".
 .\"
-.TH lpadmin 8 "Common UNIX Printing System" "13 July 2006" "Apple Inc."
+.TH lpadmin 8 "Common UNIX Printing System" "2 January 2008" "Apple Inc."
 .SH NAME
 lpadmin \- configure cups printers and classes
 .SH SYNOPSIS
@@ -81,12 +81,6 @@ and is intended for providing support for legacy printer drivers.
 Sets a standard System V interface script or PPD file from the
 \fImodel\fR directory.
 .TP 5
--o name=value
-.br
-Sets a PPD or server option for the printer. PPD options can be
-listed using the \fI-l\fR option with the \fIlpoptions(1)\fR
-command.
-.TP 5
 -o job-k-limit=value
 .br
 Sets the kilobyte limit for per-user quotas. The value is an
@@ -109,10 +103,23 @@ integer number of seconds; 86,400 seconds are in one day.
 .br
 Sets the default banner page(s) to use for print jobs.
 .TP 5
+-o name=value
+.br
+Sets a PPD option for the printer. PPD options can be
+listed using the \fI-l\fR option with the \fIlpoptions(1)\fR
+command.
+.TP 5
+-o name-default=value
+.br
+Sets a default server-side option for the printer. Any print-time
+option can be defaulted, e.g. "-o cpi-default=17" to set the default
+"cpi" option value to 17.
+.TP 5
 -o port-monitor=name
 .br
 Sets the binary communications program to use when printing,
-"none", "bcp", or "tbcp". The default program is "none".
+"none", "bcp", or "tbcp". The default program is "none". The
+specified port monitor must be listed in the printer's PPD file.
 .TP 5
 -o printer-error-policy=name
 .br
@@ -194,7 +201,7 @@ System V or Solaris printing system configuration options.
 .br
 http://localhost:631/help
 .SH COPYRIGHT
-Copyright 2007 by Apple Inc.
+Copyright 2007-2008 by Apple Inc.
 .\"
 .\" End of "$Id: lpadmin.man 6649 2007-07-11 21:46:42Z mike $".
 .\"
index fac327e10a5f40a12d0d0187ca65f4ef3fc2d70d..3be52e9f470ef50a398e5c4025f88378352a9248 100644 (file)
@@ -3,7 +3,7 @@
 .\"
 .\"   lpq man page for the Common UNIX Printing System (CUPS).
 .\"
-.\"   Copyright 2007 by Apple Inc.
+.\"   Copyright 2007-2008 by Apple Inc.
 .\"   Copyright 1997-2006 by Easy Software Products.
 .\"
 .\"   These coded instructions, statements, and computer programs are the
@@ -12,7 +12,7 @@
 .\"   which should have been included with this file.  If this file is
 .\"   file is missing or damaged, see the license at "http://www.cups.org/".
 .\"
-.TH lpq 1 "Common UNIX Printing System" "12 February 2006" "Apple Inc."
+.TH lpq 1 "Common UNIX Printing System" "2 January 2008" "Apple Inc."
 .SH NAME
 lpq \- show printer queue status
 .SH SYNOPSIS
@@ -33,7 +33,7 @@ no printer or class is specified on the command-line.
 .LP
 The \fI+interval\fR option allows you to continuously report the
 jobs in the queue until the queue is empty; the list of jobs is
-show one every \fIinterval\fR seconds.
+show once every \fIinterval\fR seconds.
 .SH OPTIONS
 \fIlpq\fR supports the following options:
 .TP 5
@@ -66,7 +66,7 @@ Requests a more verbose (long) reporting format.
 .br
 http://localhost:631/help
 .SH COPYRIGHT
-Copyright 2007 by Apple Inc.
+Copyright 2007-2008 by Apple Inc.
 .\"
 .\" End of "$Id: lpq.man 6649 2007-07-11 21:46:42Z mike $".
 .\"
index 4e8d7279ff7b913a1b24e2b62d11049764f0cca6..a583ae46c50fa792b146ce703436cb67bae4be6a 100644 (file)
@@ -308,8 +308,7 @@ main(int  argc,                             // I - Number of command-line args
     // write PostScript file
     psOut = new PSOutputDev(psFileName->getCString(), doc->getXRef(),
                             doc->getCatalog(), 1, doc->getNumPages(),
-                           psModePS, 0, 0, 0, 0, gFalse,
-                           cupsGetOption("page-ranges", num_options, options));
+                           psModePS, 0, 0, 0, 0, gFalse, NULL);
     if (psOut->isOk())
       doc->displayPages(psOut, 1, doc->getNumPages(), 72.0, 72.0, 0,
                         gTrue, gFalse, gFalse);
index 9c886ae3c60691c5c2ae0557cb5a78d52b7298c7..c14ec2d62c808a05491bbe26b896995516f6e46f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: lp.c 6649 2007-07-11 21:46:42Z mike $"
+ * "$Id: lp.c 7170 2008-01-04 02:21:30Z mike $"
  *
  *   "lp" command for the Common UNIX Printing System (CUPS).
  *
@@ -17,7 +17,6 @@
  *   main()          - Parse options and send files for printing.
  *   restart_job()   - Restart a job.
  *   set_job_attrs() - Set job attributes.
- *   sighandler()    - Signal catcher for when we print from stdin...
  */
 
 /*
 #include <cups/i18n.h>
 
 
-#ifndef WIN32
-#  include <unistd.h>
-#  include <signal.h>
-
-
 /*
  * Local functions.
  */
 
-void   sighandler(int);
-#endif /* !WIN32 */
 int    restart_job(const char *command, int job_id);
 int    set_job_attrs(const char *command, int job_id, int num_options,
                      cups_option_t *options);
 
 
-/*
- * Globals...
- */
-
-char   tempfile[1024];         /* Temporary file for printing from stdin */
-
-
 /*
  * 'main()' - Parse options and send files for printing.
  */
@@ -79,13 +64,6 @@ main(int  argc,                              /* I - Number of command-line arguments */
   int          end_options;            /* No more options? */
   int          silent;                 /* Silent or verbose output? */
   char         buffer[8192];           /* Copy buffer */
-  ssize_t      bytes;                  /* Bytes copied */
-  off_t                filesize;               /* Size of temp file */
-  int          temp;                   /* Temporary file descriptor */
-#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
-  struct sigaction action;             /* Signal action */
-  struct sigaction oldaction;          /* Old signal action */
-#endif /* HAVE_SIGACTION && !HAVE_SIGSET*/
 
 
 #ifdef __sun
@@ -635,73 +613,38 @@ main(int  argc,                           /* I - Number of command-line arguments */
 
   if (num_files > 0)
     job_id = cupsPrintFiles(printer, num_files, files, title, num_options, options);
-  else
+  else if ((job_id = cupsCreateJob(CUPS_HTTP_DEFAULT, printer,
+                                   title ? title : "(stdin)",
+                                   num_options, options)) > 0)
   {
-    num_files = 1;
-
-#ifndef WIN32
-#  if defined(HAVE_SIGSET)
-    sigset(SIGHUP, sighandler);
-    if (sigset(SIGINT, sighandler) == SIG_IGN)
-      sigset(SIGINT, SIG_IGN);
-    sigset(SIGTERM, sighandler);
-#  elif defined(HAVE_SIGACTION)
-    memset(&action, 0, sizeof(action));
-    action.sa_handler = sighandler;
-
-    sigaction(SIGHUP, &action, NULL);
-    sigaction(SIGINT, NULL, &oldaction);
-    if (oldaction.sa_handler != SIG_IGN)
-      sigaction(SIGINT, &action, NULL);
-    sigaction(SIGTERM, &action, NULL);
-#  else
-    signal(SIGHUP, sighandler);
-    if (signal(SIGINT, sighandler) == SIG_IGN)
-      signal(SIGINT, SIG_IGN);
-    signal(SIGTERM, sighandler);
-#  endif
-#endif /* !WIN32 */
-
-    temp = cupsTempFd(tempfile, sizeof(tempfile));
-
-    if (temp < 0)
-    {
-      _cupsLangPrintf(stderr,
-                     _("%s: Error - unable to create temporary file \"%s\" - %s\n"),
-                     argv[0], tempfile, strerror(errno));
-      return (1);
-    }
+    http_status_t      status;         /* Write status */
+    const char         *format;        /* Document format */
+    ssize_t            bytes;          /* Bytes read */
 
-    while ((bytes = read(0, buffer, sizeof(buffer))) > 0)
-      if (write(temp, buffer, bytes) < 0)
-      {
-       _cupsLangPrintf(stderr,
-                       _("%s: Error - unable to write to temporary file "
-                         "\"%s\" - %s\n"),
-                       argv[0], tempfile, strerror(errno));
-        close(temp);
-        unlink(tempfile);
-       return (1);
-      }
 
-    filesize = lseek(temp, 0, SEEK_CUR);
-    close(temp);
+    if (cupsGetOption("raw", num_options, options))
+      format = CUPS_FORMAT_RAW;
+    else if ((format = cupsGetOption("document-format", num_options,
+                                     options)) == NULL)
+      format = CUPS_FORMAT_AUTO;
+
+    status = cupsStartDocument(CUPS_HTTP_DEFAULT, printer, job_id, NULL,
+                               format, 1);
 
-    if (filesize <= 0)
+    while (status == HTTP_CONTINUE &&
+           (bytes = read(0, buffer, sizeof(buffer))) > 0)
+      status = cupsWriteRequestData(CUPS_HTTP_DEFAULT, buffer, bytes);
+
+    if (status != HTTP_CONTINUE)
     {
       _cupsLangPrintf(stderr,
-                     _("%s: Error - stdin is empty, so no job has been sent.\n"),
-                     argv[0]);
-      unlink(tempfile);
+                     _("%s: Error - unable to queue from stdin - %s\n"),
+                     argv[0], httpStatus(status));
       return (1);
     }
 
-    if (title)
-      job_id = cupsPrintFile(printer, tempfile, title, num_options, options);
-    else
-      job_id = cupsPrintFile(printer, tempfile, "(stdin)", num_options, options);
-
-    unlink(tempfile);
+    if (cupsFinishDocument(CUPS_HTTP_DEFAULT, printer) != IPP_OK)
+      job_id = 0;
   }
 
   if (job_id < 1)
@@ -725,13 +668,10 @@ int                                       /* O - Exit status */
 restart_job(const char *command,       /* I - Command name */
             int        job_id)         /* I - Job ID */
 {
-  http_t       *http;                  /* HTTP connection to server */
   ipp_t                *request;               /* IPP request */
   char         uri[HTTP_MAX_URI];      /* URI for job */
 
 
-  http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption());
-
   request = ippNewRequest(IPP_RESTART_JOB);
 
   sprintf(uri, "ipp://localhost/jobs/%d", job_id);
@@ -742,7 +682,7 @@ restart_job(const char *command,    /* I - Command name */
   ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
                "requesting-user-name", NULL, cupsUser());
 
-  ippDelete(cupsDoRequest(http, request, "/jobs"));
+  ippDelete(cupsDoRequest(CUPS_HTTP_DEFAULT, request, "/jobs"));
 
   if (cupsLastError() > IPP_OK_CONFLICT)
   {
@@ -764,7 +704,6 @@ set_job_attrs(const char    *command,       /* I - Command name */
               int           num_options,/* I - Number of options */
              cups_option_t *options)   /* I - Options */
 {
-  http_t       *http;                  /* HTTP connection to server */
   ipp_t                *request;               /* IPP request */
   char         uri[HTTP_MAX_URI];      /* URI for job */
 
@@ -772,8 +711,6 @@ set_job_attrs(const char    *command,       /* I - Command name */
   if (num_options == 0)
     return (0);
 
-  http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption());
-
   request = ippNewRequest(IPP_SET_JOB_ATTRIBUTES);
 
   sprintf(uri, "ipp://localhost/jobs/%d", job_id);
@@ -786,7 +723,7 @@ set_job_attrs(const char    *command,       /* I - Command name */
 
   cupsEncodeOptions(request, num_options, options);
 
-  ippDelete(cupsDoRequest(http, request, "/jobs"));
+  ippDelete(cupsDoRequest(CUPS_HTTP_DEFAULT, request, "/jobs"));
 
   if (cupsLastError() > IPP_OK_CONFLICT)
   {
@@ -798,29 +735,6 @@ set_job_attrs(const char    *command,      /* I - Command name */
 }
 
 
-#ifndef WIN32
-/*
- * 'sighandler()' - Signal catcher for when we print from stdin...
- */
-
-void
-sighandler(int s)                      /* I - Signal number */
-{
- /*
-  * Remove the temporary file we're using to print from stdin...
-  */
-
-  unlink(tempfile);
-
- /*
-  * Exit...
-  */
-
-  exit(s);
-}
-#endif /* !WIN32 */
-
-
 /*
- * End of "$Id: lp.c 6649 2007-07-11 21:46:42Z mike $".
+ * End of "$Id: lp.c 7170 2008-01-04 02:21:30Z mike $".
  */
index fd79db9b6caa436df3b39a687b8cb2297a7d7afb..088e3238fb5102f6efda12d5cf618180ebd123da 100644 (file)
@@ -2,8 +2,8 @@
 <TR><TD>&nbsp;</TD></TR>
 <TR><TD CLASS="trailer">The Common UNIX Printing System, CUPS, and
 the CUPS logo are the trademark property of
-<A HREF="http://www.apple.com">Apple Inc.</A> CUPS is copyright 2007 by Apple
-Inc., all rights reserved.</TD></TR>
+<A HREF="http://www.apple.com">Apple Inc.</A> CUPS is copyright 2007-2008 by
+Apple Inc., all rights reserved.</TD></TR>
 </TABLE>
 </BODY>
 </HTML>