]> git.ipfire.org Git - thirdparty/cups.git/blobdiff - scheduler/cups-lpd.c
Fix source file header text duplication text duplication.
[thirdparty/cups.git] / scheduler / cups-lpd.c
index 880467d1b551d9d6136220d904dfd07255798a14..8d2ea49171fcd8d6c3dc538bec0f5933a1bddf08 100644 (file)
@@ -1,53 +1,25 @@
 /*
- * "$Id: cups-lpd.c 177 2006-06-21 00:20:03Z jlovell $"
+ * Line Printer Daemon interface for CUPS.
  *
- *   Line Printer Daemon interface for the Common UNIX Printing System (CUPS).
+ * Copyright 2007-2016 by Apple Inc.
+ * Copyright 1997-2006 by Easy Software Products, all rights reserved.
  *
- *   Copyright 1997-2006 by Easy Software Products, all rights reserved.
- *
- *   These coded instructions, statements, and computer programs are the
- *   property of Easy Software Products and are protected by Federal
- *   copyright law.  Distribution and use rights are outlined in the file
- *   "LICENSE.txt" which should have been included with this file.  If this
- *   file is missing or damaged please contact Easy Software Products
- *   at:
- *
- *       Attn: CUPS Licensing Information
- *       Easy Software Products
- *       44141 Airport View Drive, Suite 204
- *       Hollywood, Maryland 20636 USA
- *
- *       Voice: (301) 373-9600
- *       EMail: cups-info@cups.org
- *         WWW: http://www.cups.org
- *
- * Contents:
- *
- *   main()           - Process an incoming LPD request...
- *   create_job()     - Create a new print job.
- *   get_printer()    - Get the named printer and its options.
- *   print_file()     - Add a file to the current job.
- *   recv_print_job() - Receive a print job from the client.
- *   remove_jobs()    - Cancel one or more jobs.
- *   send_state()     - Send the queue state.
- *   smart_gets()     - Get a line of text, removing the trailing CR and/or LF.
+ * These coded instructions, statements, and computer programs are the
+ * property of Apple Inc. and are protected by Federal copyright
+ * law.  Distribution and use rights are outlined in the file "LICENSE.txt"
+ * which should have been included with this file.  If this file is
+ * missing or damaged, see the license at "http://www.cups.org/".
  */
 
 /*
  * Include necessary headers...
  */
 
-#include <cups/http-private.h>
-#include <cups/cups.h>
-#include <cups/string.h>
-#include <cups/language.h>
-#include <stdlib.h>
-#include <errno.h>
+#define _CUPS_NO_DEPRECATED
+#include <cups/cups-private.h>
 #include <syslog.h>
-#include <ctype.h>
 #include <unistd.h>
 #include <fcntl.h>
-
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <netinet/in.h>
 #ifdef HAVE_INTTYPES_H
 #  include <inttypes.h>
 #endif /* HAVE_INTTYPES_H */
-
-#ifdef HAVE_COREFOUNDATION_H
-#  include <CoreFoundation/CoreFoundation.h>
-#endif /* HAVE_COREFOUNDATION_H */
-#ifdef HAVE_CFPRIV_H
-#  include <CoreFoundation/CFPriv.h>
-#endif /* HAVE_CFPRIV_H */
+#ifdef __APPLE__
+#  include <vproc.h>
+#endif /* __APPLE__ */
 
 
 /*
  * Prototypes...
  */
 
-static int     create_job(http_t *http, const char *dest, const char *title,
-                          const char *user, int num_options,
-                          cups_option_t *options);
+static int     create_job(http_t *http, const char *dest, const char *title, const char *user, int num_options, cups_option_t *options);
 static int     get_printer(http_t *http, const char *name, char *dest,
-                           int destsize, cups_option_t **options,
+                           size_t destsize, cups_option_t **options,
                            int *accepting, int *shared, ipp_pstate_t *state);
 static int     print_file(http_t *http, int id, const char *filename,
-                          const char *docname, const char *user, int last);
+                          const char *docname, const char *user,
+                          const char *format, int last);
 static int     recv_print_job(const char *name, int num_defaults,
                               cups_option_t *defaults);
 static int     remove_jobs(const char *name, const char *agent,
@@ -104,6 +71,7 @@ static int   remove_jobs(const char *name, const char *agent,
 static int     send_state(const char *name, const char *list,
                           int longstatus);
 static char    *smart_gets(char *s, int len, FILE *fp);
+static void    smart_strlcpy(char *dst, const char *src, size_t dstsize);
 
 
 /*
@@ -129,6 +97,9 @@ main(int  argc,                              /* I - Number of command-line arguments */
                hostip[256],            /* IP address */
                *hostfamily;            /* Address family */
   int          hostlookups;            /* Do hostname lookups? */
+#ifdef __APPLE__
+  vproc_transaction_t vtran = vproc_transaction_begin(NULL);
+#endif /* __APPLE__ */
 
 
  /*
@@ -150,14 +121,25 @@ main(int  argc,                           /* I - Number of command-line arguments */
   num_defaults = 0;
   defaults     = NULL;
   hostlookups  = 1;
-  num_defaults = cupsAddOption("job-originating-host-name", hostname,
-                               num_defaults, &defaults);
 
   for (i = 1; i < argc; i ++)
     if (argv[i][0] == '-')
     {
       switch (argv[i][1])
       {
+        case 'h' : /* -h hostname[:port] */
+            if (argv[i][2])
+             cupsSetServer(argv[i] + 2);
+           else
+           {
+             i ++;
+             if (i < argc)
+               cupsSetServer(argv[i]);
+             else
+               syslog(LOG_WARNING, "Expected hostname string after -h option!");
+           }
+           break;
+
        case 'o' : /* Option */
            if (argv[i][2])
              num_defaults = cupsParseOptions(argv[i] + 2, num_defaults,
@@ -195,7 +177,7 @@ main(int  argc,                             /* I - Number of command-line arguments */
   if (getpeername(0, (struct sockaddr *)&hostaddr, &hostlen))
   {
     syslog(LOG_WARNING, "Unable to get client address - %s", strerror(errno));
-    strcpy(hostname, "unknown");
+    strlcpy(hostname, "unknown", sizeof(hostname));
   }
   else
   {
@@ -217,6 +199,9 @@ main(int  argc,                             /* I - Number of command-line arguments */
            hostip);
   }
 
+  num_defaults = cupsAddOption("job-originating-host-name", hostname,
+                               num_defaults, &defaults);
+
  /*
   * RFC1179 specifies that only 1 daemon command can be received for
   * every connection.
@@ -230,6 +215,11 @@ main(int  argc,                            /* I - Number of command-line arguments */
 
     syslog(LOG_ERR, "Unable to get command line from client!");
     putchar(1);
+
+#ifdef __APPLE__
+    vproc_transaction_end(NULL, vtran);
+#endif /* __APPLE__ */
+
     return (1);
   }
 
@@ -238,14 +228,16 @@ main(int  argc,                           /* I - Number of command-line arguments */
   * resource list, and/or user name.
   */
 
-  command = line[0];
-  dest    = line + 1;
+  if ((command = line[0]) == '\0')
+    dest = line;
+  else
+    dest = line + 1;
 
   if (command == 0x02)
     list = NULL;
   else
   {
-    for (list = dest + 1; *list && !isspace(*list & 255); list ++);
+    for (list = dest; *list && !isspace(*list & 255); list ++);
 
     while (isspace(*list & 255))
       *list++ = '\0';
@@ -276,37 +268,42 @@ main(int  argc,                           /* I - Number of command-line arguments */
         syslog(LOG_INFO, "Receive print job for %s", dest);
         /* recv_print_job() sends initial status byte */
 
-        status = recv_print_job(dest, num_defaults, defaults);
+        status = (char)recv_print_job(dest, num_defaults, defaults);
        break;
 
     case 0x03 : /* Send queue state (short) */
         syslog(LOG_INFO, "Send queue state (short) for %s %s", dest, list);
        /* no status byte for this command */
 
-        status = send_state(dest, list, 0);
+        status = (char)send_state(dest, list, 0);
        break;
 
     case 0x04 : /* Send queue state (long) */
         syslog(LOG_INFO, "Send queue state (long) for %s %s", dest, list);
        /* no status byte for this command */
 
-        status = send_state(dest, list, 1);
+        status = (char)send_state(dest, list, 1);
        break;
 
     case 0x05 : /* Remove jobs */
-       /*
-        * Grab the agent and skip to the list of users and/or jobs.
-       */
+        if (list)
+       {
+        /*
+         * Grab the agent and skip to the list of users and/or jobs.
+         */
 
-        agent = list;
+         agent = list;
 
-       for (; *list && !isspace(*list & 255); list ++);
-       while (isspace(*list & 255))
-         *list++ = '\0';
+         for (; *list && !isspace(*list & 255); list ++);
+         while (isspace(*list & 255))
+           *list++ = '\0';
 
-        syslog(LOG_INFO, "Remove jobs %s on %s by %s", list, dest, agent);
+         syslog(LOG_INFO, "Remove jobs %s on %s by %s", list, dest, agent);
 
-        status = remove_jobs(dest, agent, list);
+         status = (char)remove_jobs(dest, agent, list);
+        }
+       else
+         status = 1;
 
        putchar(status);
        break;
@@ -315,6 +312,10 @@ main(int  argc,                            /* I - Number of command-line arguments */
   syslog(LOG_INFO, "Closing connection");
   closelog();
 
+#ifdef __APPLE__
+  vproc_transaction_end(NULL, vtran);
+#endif /* __APPLE__ */
+
   return (status);
 }
 
@@ -327,7 +328,7 @@ static int                          /* O - Job ID or -1 on error */
 create_job(http_t        *http,                /* I - HTTP connection */
            const char    *dest,                /* I - Destination name */
           const char    *title,        /* I - job-name */
-           const char    *user,                /* I - requesting-user-name */
+          const char    *user,         /* I - requesting-user-name */
           int           num_options,   /* I - Number of options for job */
           cups_option_t *options)      /* I - Options for job */
 {
@@ -342,7 +343,7 @@ create_job(http_t        *http,             /* I - HTTP connection */
   * Setup the Create-Job request...
   */
 
-  request = ippNewRequest(IPP_CREATE_JOB);
+  request = ippNewRequest(IPP_OP_CREATE_JOB);
 
   httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
                    "localhost", 0, "/printers/%s", dest);
@@ -353,7 +354,7 @@ create_job(http_t        *http,             /* I - HTTP connection */
   ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
                "requesting-user-name", NULL, user);
 
-  if (title)
+  if (title[0])
     ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "job-name",
                  NULL, title);
 
@@ -367,7 +368,7 @@ create_job(http_t        *http,             /* I - HTTP connection */
 
   response = cupsDoRequest(http, request, uri);
 
-  if (!response || cupsLastError() > IPP_OK_CONFLICT)
+  if (!response || cupsLastError() > IPP_STATUS_OK_CONFLICTING)
   {
     syslog(LOG_ERR, "Unable to create job - %s", cupsLastErrorString());
 
@@ -407,7 +408,7 @@ static int                          /* O - Number of options or -1 on error */
 get_printer(http_t        *http,       /* I - HTTP connection */
             const char    *name,       /* I - Printer name from request */
            char          *dest,        /* I - Destination buffer */
-            int           destsize,    /* I - Size of destination buffer */
+            size_t        destsize,    /* I - Size of destination buffer */
            cups_option_t **options,    /* O - Printer options */
            int           *accepting,   /* O - printer-is-accepting-jobs value */
            int           *shared,      /* O - printer-is-shared value */
@@ -443,19 +444,46 @@ get_printer(http_t        *http,  /* I - HTTP connection */
   if (shared)
     *shared = 0;
   if (state)
-    *state = IPP_PRINTER_STOPPED;
+    *state = IPP_PSTATE_STOPPED;
   if (options)
     *options = NULL;
 
  /*
-  * If the queue name contains a space, lookup the printer-name using
-  * the printer-info value...
+  * See if the name is a queue name optionally with an instance name.
+  */
+
+  strlcpy(dest, name, destsize);
+  if ((value = strchr(dest, '/')) != NULL)
+    *value = '\0';
+
+ /*
+  * Setup the Get-Printer-Attributes request...
   */
 
-  if (strchr(name, ' '))
+  request = ippNewRequest(IPP_OP_GET_PRINTER_ATTRIBUTES);
+
+  httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
+                  "localhost", 0, "/printers/%s", dest);
+
+  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
+              NULL, uri);
+
+  ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
+               "requested-attributes",
+               (int)(sizeof(requested) / sizeof(requested[0])),
+               NULL, requested);
+
+ /*
+  * Do the request...
+  */
+
+  response = cupsDoRequest(http, request, "/");
+
+  if (!response || cupsLastError() > IPP_STATUS_OK_CONFLICTING)
   {
    /*
-    * Lookup the printer-info...
+    * If we can't find the printer by name, look up the printer-name
+    * using the printer-info values...
     */
 
     ipp_attribute_t    *accepting_attr,/* printer-is-accepting-jobs */
@@ -465,13 +493,15 @@ get_printer(http_t        *http,  /* I - HTTP connection */
                        *state_attr;    /* printer-state */
 
 
+    ippDelete(response);
+
    /*
     * Setup the CUPS-Get-Printers request...
     */
 
-    request = ippNewRequest(CUPS_GET_PRINTERS);
+    request = ippNewRequest(IPP_OP_CUPS_GET_PRINTERS);
 
-    ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
+    ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
                   "requested-attributes",
                  (int)(sizeof(requested) / sizeof(requested[0])),
                   NULL, requested);
@@ -482,7 +512,7 @@ get_printer(http_t        *http,    /* I - HTTP connection */
 
     response = cupsDoRequest(http, request, "/");
 
-    if (!response || cupsLastError() > IPP_OK_CONFLICT)
+    if (!response || cupsLastError() > IPP_STATUS_OK_CONFLICTING)
     {
       syslog(LOG_ERR, "Unable to get list of printers - %s",
              cupsLastErrorString());
@@ -543,7 +573,7 @@ get_printer(http_t        *http,    /* I - HTTP connection */
       }
 
       if (info_attr && name_attr &&
-          !strcasecmp(name, info_attr->values[0].string.text))
+          !_cups_strcasecmp(name, info_attr->values[0].string.text))
       {
        /*
         * Found a match, use this one!
@@ -577,47 +607,6 @@ get_printer(http_t        *http,   /* I - HTTP connection */
   }
   else
   {
-   /*
-    * Otherwise treat it as a queue name optionally with an instance name.
-    */
-
-    strlcpy(dest, name, destsize);
-    if ((value = strchr(dest, '/')) != NULL)
-      *value = '\0';
-
-   /*
-    * Setup the Get-Printer-Attributes request...
-    */
-
-    request = ippNewRequest(IPP_GET_PRINTER_ATTRIBUTES);
-
-    httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
-                     "localhost", 0, "/printers/%s", dest);
-
-    ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
-                NULL, uri);
-
-    ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
-                  "requested-attributes",
-                 (int)(sizeof(requested) / sizeof(requested[0])),
-                  NULL, requested);
-
-   /*
-    * Do the request...
-    */
-
-    response = cupsDoRequest(http, request, "/");
-
-    if (!response || cupsLastError() > IPP_OK_CONFLICT)
-    {
-      syslog(LOG_ERR, "Unable to check printer status - %s",
-             cupsLastErrorString());
-
-      ippDelete(response);
-
-      return (-1);
-    }
-
    /*
     * Get values from the response...
     */
@@ -625,9 +614,9 @@ get_printer(http_t        *http,    /* I - HTTP connection */
     if (accepting)
     {
       if ((attr = ippFindAttribute(response, "printer-is-accepting-jobs",
-                                  IPP_TAG_BOOLEAN)) == NULL)
+                                  IPP_TAG_BOOLEAN)) == NULL)
        syslog(LOG_ERR, "No printer-is-accepting-jobs attribute found in "
-                       "response from server!");
+                       "response from server!");
       else
        *accepting = attr->values[0].boolean;
     }
@@ -635,10 +624,10 @@ get_printer(http_t        *http,  /* I - HTTP connection */
     if (shared)
     {
       if ((attr = ippFindAttribute(response, "printer-is-shared",
-                                  IPP_TAG_BOOLEAN)) == NULL)
+                                  IPP_TAG_BOOLEAN)) == NULL)
       {
        syslog(LOG_ERR, "No printer-is-shared attribute found in "
-                       "response from server!");
+                       "response from server!");
        *shared = 1;
       }
       else
@@ -648,9 +637,9 @@ get_printer(http_t        *http,    /* I - HTTP connection */
     if (state)
     {
       if ((attr = ippFindAttribute(response, "printer-state",
-                                  IPP_TAG_INTEGER)) == NULL)
+                                  IPP_TAG_ENUM)) == NULL)
        syslog(LOG_ERR, "No printer-state attribute found in "
-                       "response from server!");
+                       "response from server!");
       else
        *state = (ipp_pstate_t)attr->values[0].integer;
     }
@@ -658,102 +647,6 @@ get_printer(http_t        *http,  /* I - HTTP connection */
     ippDelete(response);
   }
 
- /*
-  * Override shared value for LPD using system-specific APIs...
-  */
-
-#ifdef HAVE_CFPRIV_H /* MacOS X */
-  if (shared && *shared)
-  {
-    CFURLRef           prefsurl;       /* */
-    CFDataRef          xmldata;        /* */
-    CFPropertyListRef  plist;          /* */
-    CFStringRef                queueid;        /* */
-    CFArrayRef         lprqarray;      /* */
-    CFBooleanRef       serverflag;     /* */
-    Boolean            prefsok;        /* */
-    static const char printerprefsfile[] =
-        "/Library/Preferences/com.apple.printservice.plist";
-                                       /* Preferences file */
-
-
-   /*
-    * See if we are running on MacOS X Server...
-    */
-
-    CFDictionaryRef versdict = _CFCopyServerVersionDictionary();
-
-    if (versdict)
-    {
-     /*
-      * Yes, use the LPR sharing preference...
-      */
-
-      CFRelease(versdict);
-
-      *shared = 0;
-
-      prefsurl = CFURLCreateFromFileSystemRepresentation(
-                     kCFAllocatorDefault, 
-                    (const UInt8 *)printerprefsfile, 
-                    (CFIndex)strlen(printerprefsfile), 
-                    false);
-      if (prefsurl)
-      {
-        prefsok = CFURLCreateDataAndPropertiesFromResource(
-                     kCFAllocatorDefault, prefsurl, &xmldata, 
-                     NULL, NULL, NULL);
-        if (prefsok)
-       {
-         plist = CFPropertyListCreateFromXMLData(kCFAllocatorDefault, xmldata, 
-                                                 kCFPropertyListImmutable, NULL);
-         if (plist)
-         {
-           serverflag = (CFBooleanRef)CFDictionaryGetValue(
-                            (CFDictionaryRef)plist, CFSTR("serviceState"));
-
-            if (serverflag && CFBooleanGetValue(serverflag))
-           {
-             lprqarray = (CFArrayRef)CFDictionaryGetValue(
-                             (CFDictionaryRef)plist, CFSTR("lprSharedQueues"));
-
-             if (lprqarray)
-             {
-               queueid = CFStringCreateWithCString(CFAllocatorGetDefault(), 
-                                                   dest,
-                                                   kCFStringEncodingUTF8);
-
-                if (queueid)
-               {
-                 *shared = CFArrayContainsValue(
-                               lprqarray,
-                               CFRangeMake(0, CFArrayGetCount(lprqarray)),
-                               queueid);
-
-                  CFRelease(queueid);
-               }
-
-                CFRelease(lprqarray);
-             }
-           }
-
-            if (serverflag)
-             CFRelease(serverflag);
-
-           CFRelease(plist);
-         }
-       }
-
-       CFRelease(prefsurl);
-      }
-
-      if (!shared)
-       syslog(LOG_ERR, "Warning - Print Service sharing disabled for LPD "
-                       "on queue: %s", name);
-    }
-  }
-#endif /* HAVE_CFPRIV_H */
-
  /*
   * Next look for the printer in the lpoptions file...
   */
@@ -775,7 +668,7 @@ get_printer(http_t        *http,    /* I - HTTP connection */
        * Make sure we have "Dest name options" or "Default name options"...
        */
 
-       if ((strcasecmp(line, "Dest") && strcasecmp(line, "Default")) || !value)
+       if ((_cups_strcasecmp(line, "Dest") && _cups_strcasecmp(line, "Default")) || !value)
           continue;
 
        /*
@@ -792,7 +685,7 @@ get_printer(http_t        *http,    /* I - HTTP connection */
        * the loop - we're done!
        */
 
-       if (!strcasecmp(value, name))
+       if (!_cups_strcasecmp(value, name))
        {
           num_options = cupsParseOptions(optptr, num_options, options);
          break;
@@ -823,6 +716,7 @@ print_file(http_t     *http,                /* I - HTTP connection */
           const char *filename,        /* I - File to print */
            const char *docname,                /* I - document-name */
           const char *user,            /* I - requesting-user-name */
+          const char *format,          /* I - document-format */
           int        last)             /* I - 1 = last file in job */
 {
   ipp_t                *request;               /* IPP request */
@@ -833,7 +727,7 @@ print_file(http_t     *http,                /* I - HTTP connection */
   * Setup the Send-Document request...
   */
 
-  request = ippNewRequest(IPP_SEND_DOCUMENT);
+  request = ippNewRequest(IPP_OP_SEND_DOCUMENT);
 
   snprintf(uri, sizeof(uri), "ipp://localhost/jobs/%d", id);
   ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri", NULL, uri);
@@ -845,8 +739,11 @@ print_file(http_t     *http,               /* I - HTTP connection */
     ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
                 "document-name", NULL, docname);
 
-  if (last)
-    ippAddBoolean(request, IPP_TAG_OPERATION, "last-document", 1);
+  if (format)
+    ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_MIMETYPE,
+                 "document-format", NULL, format);
+
+  ippAddBoolean(request, IPP_TAG_OPERATION, "last-document", (char)last);
 
  /*
   * Do the request...
@@ -856,7 +753,7 @@ print_file(http_t     *http,                /* I - HTTP connection */
 
   ippDelete(cupsDoFileRequest(http, request, uri, filename));
 
-  if (cupsLastError() > IPP_OK_CONFLICT)
+  if (cupsLastError() > IPP_STATUS_OK_CONFLICTING)
   {
     syslog(LOG_ERR, "Unable to send document - %s", cupsLastErrorString());
 
@@ -883,7 +780,8 @@ recv_print_job(
   int          fd;                     /* Temporary file */
   FILE         *fp;                    /* File pointer */
   char         filename[1024];         /* Temporary filename */
-  int          bytes;                  /* Bytes received */
+  ssize_t      bytes;                  /* Bytes received */
+  size_t       total;                  /* Total bytes */
   char         line[256],              /* Line from file/stdin */
                command,                /* Command from line */
                *count,                 /* Number of bytes */
@@ -910,7 +808,7 @@ recv_print_job(
   * Connect to the server...
   */
 
-  http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption());
+  http = httpConnect2(cupsServer(), ippPort(), NULL, AF_UNSPEC, cupsEncryption(), 1, 30000, NULL);
   if (!http)
   {
     syslog(LOG_ERR, "Unable to connect to server: %s", strerror(errno));
@@ -1016,7 +914,7 @@ recv_print_job(
              break;
            }
 
-           strcpy(filename, control);
+           strlcpy(filename, control, sizeof(filename));
          }
          break;
 
@@ -1052,7 +950,7 @@ recv_print_job(
            break;
          }
 
-         strcpy(filename, temp[num_data]);
+         strlcpy(filename, temp[num_data], sizeof(filename));
 
           num_data ++;
          break;
@@ -1067,15 +965,15 @@ recv_print_job(
     * Copy the data or control file from the client...
     */
 
-    for (i = atoi(count); i > 0; i -= bytes)
+    for (total = (size_t)strtoll(count, NULL, 10); total > 0; total -= (size_t)bytes)
     {
-      if (i > sizeof(line))
-        bytes = sizeof(line);
+      if (total > sizeof(line))
+        bytes = (ssize_t)sizeof(line);
       else
-        bytes = i;
+        bytes = (ssize_t)total;
 
-      if ((bytes = fread(line, 1, bytes, stdin)) > 0)
-        bytes = write(fd, line, bytes);
+      if ((bytes = (ssize_t)fread(line, 1, (size_t)bytes, stdin)) > 0)
+        bytes = write(fd, line, (size_t)bytes);
 
       if (bytes < 1)
       {
@@ -1141,9 +1039,10 @@ recv_print_job(
       * Grab the job information...
       */
 
-      title[0] = '\0';
-      user[0]  = '\0';
-      doccount = 0;
+      title[0]   = '\0';
+      user[0]    = '\0';
+      docname[0] = '\0';
+      doccount   = 0;
 
       while (smart_gets(line, sizeof(line), fp) != NULL)
       {
@@ -1154,11 +1053,15 @@ recv_print_job(
        switch (line[0])
        {
          case 'J' : /* Job name */
-             strlcpy(title, line + 1, sizeof(title));
+             smart_strlcpy(title, line + 1, sizeof(title));
              break;
 
+          case 'N' : /* Document name */
+              smart_strlcpy(docname, line + 1, sizeof(docname));
+              break;
+
          case 'P' : /* User identification */
-             strlcpy(user, line + 1, sizeof(user));
+             smart_strlcpy(user, line + 1, sizeof(user));
              break;
 
          case 'L' : /* Print banner page */
@@ -1213,7 +1116,7 @@ recv_print_job(
       {
        syslog(LOG_WARNING, "No username specified by client! "
                            "Using \"anonymous\"...");
-       strcpy(user, "anonymous");
+       strlcpy(user, "anonymous", sizeof(user));
       }
 
      /*
@@ -1242,7 +1145,7 @@ recv_print_job(
          switch (line[0])
          {
            case 'N' : /* Document name */
-               strlcpy(docname, line + 1, sizeof(docname));
+               smart_strlcpy(docname, line + 1, sizeof(docname));
                break;
 
            case 'c' : /* Plot CIF file */
@@ -1277,6 +1180,8 @@ recv_print_job(
                docnumber ++;
 
                if (print_file(http, id, temp[i], docname, user,
+                              cupsGetOption("document-format", num_options,
+                                            options),
                               docnumber == doccount))
                   status = 1;
                else
@@ -1288,9 +1193,9 @@ recv_print_job(
          if (status)
            break;
        }
-
-       fclose(fp);
       }
+
+      fclose(fp);
     }
   }
 
@@ -1332,8 +1237,7 @@ remove_jobs(const char *dest,             /* I - Destination */
   * Try connecting to the local server...
   */
 
-  if ((http = httpConnectEncrypt(cupsServer(), ippPort(),
-                                 cupsEncryption())) == NULL)
+  if ((http = httpConnect2(cupsServer(), ippPort(), NULL, AF_UNSPEC, cupsEncryption(), 1, 30000, NULL)) == NULL)
   {
     syslog(LOG_ERR, "Unable to connect to server %s: %s", cupsServer(),
            strerror(errno));
@@ -1356,7 +1260,7 @@ remove_jobs(const char *dest,             /* I - Destination */
       list ++;
 
    /*
-    * Build an IPP_CANCEL_JOB request, which requires the following
+    * Build an IPP_OP_CANCEL_JOB request, which requires the following
     * attributes:
     *
     *    attributes-charset
@@ -1365,7 +1269,7 @@ remove_jobs(const char *dest,             /* I - Destination */
     *    requesting-user-name
     */
 
-    request = ippNewRequest(IPP_CANCEL_JOB);
+    request = ippNewRequest(IPP_OP_CANCEL_JOB);
 
     sprintf(uri, "ipp://localhost/jobs/%d", id);
     ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri", NULL, uri);
@@ -1379,7 +1283,7 @@ remove_jobs(const char *dest,             /* I - Destination */
 
     ippDelete(cupsDoRequest(http, request, "/jobs"));
 
-    if (cupsLastError() > IPP_OK_CONFLICT)
+    if (cupsLastError() > IPP_STATUS_OK_CONFLICTING)
     {
       syslog(LOG_WARNING, "Cancel of job ID %d failed: %s\n", id,
              cupsLastErrorString());
@@ -1387,7 +1291,7 @@ remove_jobs(const char *dest,             /* I - Destination */
       return (1);
     }
     else
-      syslog(LOG_INFO, "Job ID %d cancelled", id);
+      syslog(LOG_INFO, "Job ID %d canceled", id);
   }
 
   httpClose(http);
@@ -1453,8 +1357,7 @@ send_state(const char *queue,             /* I - Destination */
   * Try connecting to the local server...
   */
 
-  if ((http = httpConnectEncrypt(cupsServer(), ippPort(),
-                                 cupsEncryption())) == NULL)
+  if ((http = httpConnect2(cupsServer(), ippPort(), NULL, AF_UNSPEC, cupsEncryption(), 1, 30000, NULL)) == NULL)
   {
     syslog(LOG_ERR, "Unable to connect to server %s: %s", cupsServer(),
            strerror(errno));
@@ -1480,19 +1383,19 @@ send_state(const char *queue,           /* I - Destination */
 
   switch (state)
   {
-    case IPP_PRINTER_IDLE :
+    case IPP_PSTATE_IDLE :
         printf("%s is ready\n", dest);
        break;
-    case IPP_PRINTER_PROCESSING :
+    case IPP_PSTATE_PROCESSING :
         printf("%s is ready and printing\n", dest);
        break;
-    case IPP_PRINTER_STOPPED :
+    case IPP_PSTATE_STOPPED :
         printf("%s is not ready\n", dest);
        break;
   }
 
  /*
-  * Build an IPP_GET_JOBS or IPP_GET_JOB_ATTRIBUTES request, which requires
+  * Build an IPP_OP_GET_JOBS or IPP_OP_GET_JOB_ATTRIBUTES request, which requires
   * the following attributes:
   *
   *    attributes-charset
@@ -1502,7 +1405,7 @@ send_state(const char *queue,             /* I - Destination */
 
   id = atoi(list);
 
-  request = ippNewRequest(id ? IPP_GET_JOB_ATTRIBUTES : IPP_GET_JOBS);
+  request = ippNewRequest(id ? IPP_OP_GET_JOB_ATTRIBUTES : IPP_OP_GET_JOBS);
 
   httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
                    "localhost", 0, "/printers/%s", dest);
@@ -1531,7 +1434,7 @@ send_state(const char *queue,             /* I - Destination */
   jobcount = 0;
   response = cupsDoRequest(http, request, "/");
 
-  if (cupsLastError() > IPP_OK_CONFLICT)
+  if (cupsLastError() > IPP_STATUS_OK_CONFLICTING)
   {
     printf("get-jobs failed: %s\n", cupsLastErrorString());
     ippDelete(response);
@@ -1560,7 +1463,7 @@ send_state(const char *queue,             /* I - Destination */
 
     jobid     = 0;
     jobsize   = 0;
-    jobstate  = IPP_JOB_PENDING;
+    jobstate  = IPP_JSTATE_PENDING;
     jobname   = "untitled";
     jobuser   = NULL;
     jobdest   = NULL;
@@ -1621,8 +1524,8 @@ send_state(const char *queue,             /* I - Destination */
     * Display the job...
     */
 
-    if (jobstate == IPP_JOB_PROCESSING)
-      strcpy(rankstr, "active");
+    if (jobstate == IPP_JSTATE_PROCESSING)
+      strlcpy(rankstr, "active", sizeof(rankstr));
     else
     {
       snprintf(rankstr, sizeof(rankstr), "%d%s", rank, ranks[rank % 10]);
@@ -1703,7 +1606,7 @@ smart_gets(char *s,                       /* I - Pointer to line buffer */
       break;
     }
     else if (ptr < end)
-      *ptr++ = ch;
+      *ptr++ = (char)ch;
   }
 
   *ptr = '\0';
@@ -1716,5 +1619,91 @@ smart_gets(char *s,                      /* I - Pointer to line buffer */
 
 
 /*
- * End of "$Id: cups-lpd.c 177 2006-06-21 00:20:03Z jlovell $".
+ * 'smart_strlcpy()' - Copy a string and convert from ISO-8859-1 to UTF-8 as needed.
  */
+
+static void
+smart_strlcpy(char       *dst,         /* I - Output buffer */
+              const char *src,         /* I - Input string */
+              size_t     dstsize)      /* I - Size of output buffer */
+{
+  const unsigned char  *srcptr;        /* Pointer into input string */
+  unsigned char                *dstptr,        /* Pointer into output buffer */
+                       *dstend;        /* End of output buffer */
+  int                  saw_8859 = 0;   /* Saw an extended character that was not UTF-8? */
+
+
+  for (srcptr = (unsigned char *)src, dstptr = (unsigned char *)dst, dstend = dstptr + dstsize - 1; *srcptr;)
+  {
+    if (*srcptr < 0x80)
+      *dstptr++ = *srcptr++;           /* ASCII */
+    else if (saw_8859)
+    {
+     /*
+      * Map ISO-8859-1 (most likely character set for legacy LPD clients) to
+      * UTF-8...
+      */
+
+      if (dstptr > (dstend - 2))
+        break;
+
+      *dstptr++ = 0xc0 | (*srcptr >> 6);
+      *dstptr++ = 0x80 | (*srcptr++ & 0x3f);
+    }
+    else if ((*srcptr & 0xe0) == 0xc0 && (srcptr[1] & 0xc0) == 0x80)
+    {
+     /*
+      * 2-byte UTF-8 sequence...
+      */
+
+      if (dstptr > (dstend - 2))
+        break;
+
+      *dstptr++ = *srcptr++;
+      *dstptr++ = *srcptr++;
+    }
+    else if ((*srcptr & 0xf0) == 0xe0 && (srcptr[1] & 0xc0) == 0x80 && (srcptr[2] & 0xc0) == 0x80)
+    {
+     /*
+      * 3-byte UTF-8 sequence...
+      */
+
+      if (dstptr > (dstend - 3))
+        break;
+
+      *dstptr++ = *srcptr++;
+      *dstptr++ = *srcptr++;
+      *dstptr++ = *srcptr++;
+    }
+    else if ((*srcptr & 0xf8) == 0xf0 && (srcptr[1] & 0xc0) == 0x80 && (srcptr[2] & 0xc0) == 0x80 && (srcptr[3] & 0xc0) == 0x80)
+    {
+     /*
+      * 4-byte UTF-8 sequence...
+      */
+
+      if (dstptr > (dstend - 4))
+        break;
+
+      *dstptr++ = *srcptr++;
+      *dstptr++ = *srcptr++;
+      *dstptr++ = *srcptr++;
+      *dstptr++ = *srcptr++;
+    }
+    else
+    {
+     /*
+      * Bad UTF-8 sequence, this must be an ISO-8859-1 string...
+      */
+
+      saw_8859 = 1;
+
+      if (dstptr > (dstend - 2))
+        break;
+
+      *dstptr++ = 0xc0 | (*srcptr >> 6);
+      *dstptr++ = 0x80 | (*srcptr++ & 0x3f);
+    }
+  }
+
+  *dstptr = '\0';
+}