]> git.ipfire.org Git - thirdparty/cups.git/commitdiff
Merge changes from CUPS 1.6svn-r10112.
authormsweet <msweet@a1ca3aef-8c08-0410-bb20-df032aa958be>
Tue, 8 Nov 2011 00:30:03 +0000 (00:30 +0000)
committermsweet <msweet@a1ca3aef-8c08-0410-bb20-df032aa958be>
Tue, 8 Nov 2011 00:30:03 +0000 (00:30 +0000)
git-svn-id: svn+ssh://src.apple.com/svn/cups/easysw/current@3486 a1ca3aef-8c08-0410-bb20-df032aa958be

94 files changed:
CHANGES-1.5.txt
CHANGES-IPPTOOL.txt
CHANGES.txt
Makedefs.in
Makefile
backend/backend-private.h
backend/ipp.c
backend/snmp-supplies.c
cgi-bin/admin.c
cgi-bin/cgi-private.h
config-scripts/cups-common.m4
config-scripts/cups-defaults.m4
config-scripts/cups-gssapi.m4
config-scripts/cups-ldap.m4 [deleted file]
config-scripts/cups-slp.m4 [deleted file]
config.h.in
configure.in
cups/Makefile
cups/adminutil.c
cups/adminutil.h
cups/api-ppd.header
cups/api-ppd.shtml
cups/auth.c
cups/cups.h
cups/encode.c
cups/http.c
cups/http.h
cups/ipp-private.h
cups/ipp-support.c
cups/ipp.c
cups/ipp.h
cups/language.c
cups/libcups_s.exp
cups/ppd-cache.c
cups/ppd.h
cups/pwg-media.c
cups/testipp.c
cups/versioning.h
doc/help/api-httpipp.html
doc/help/api-ppd.html
doc/help/man-ipptool.html [new file with mode: 0644]
doc/help/man-ipptoolfile.html [new file with mode: 0644]
doc/help/ref-cupsd-conf.html.in
doc/help/ref-page_log.html
filter/interpret.c
filter/raster.c
man/cupsd.conf.man.in
notifier/mailto.c
notifier/rss.c
notifier/testnotify.c
scheduler/Makefile
scheduler/cert.c
scheduler/classes.c
scheduler/classes.h
scheduler/client.c
scheduler/conf.c
scheduler/conf.h
scheduler/cups-driverd.cxx
scheduler/cups-polld.c [deleted file]
scheduler/dirsvc.c
scheduler/dirsvc.h
scheduler/ipp.c
scheduler/job.c
scheduler/main.c
scheduler/printers.c
scheduler/printers.h
scheduler/server.c
scheduler/sysman.c
scheduler/sysman.h
scheduler/testdirsvc.c [deleted file]
scheduler/testsub.c
systemv/cupsctl.c
systemv/lpadmin.c
systemv/lpstat.c
templates/admin.tmpl
test/5.1-lpadmin.sh
test/5.2-lpc.sh
test/5.3-lpq.sh
test/5.4-lpstat.sh
test/5.5-lp.sh
test/5.6-lpr.sh
test/5.7-lprm.sh
test/5.8-cancel.sh
test/5.9-lpinfo.sh
test/ipp-1.1.test
test/ippserver.c
test/ipptool.c
test/run-stp-tests.sh
vcnet/cups.sln
vcnet/cupstestppd.vcproj
vcnet/ipptool-installer.vdproj [new file with mode: 0644]
vcnet/ipptool.vcproj
vcnet/testfile.vcproj
vcnet/testhttp.vcproj

index 736f43be451ec363b1b40987d2e48783d4ea719e..88de1a9d48bb5452afdde82c6c7bc551d7f87911 100644 (file)
@@ -3,7 +3,19 @@ CHANGES-1.5.txt
 
 CHANGES IN CUPS V1.5.1
 
-       - Documentation updates (STR #3885, STR #3946)
+       - Documentation updates (STR #3885, STR #3946, STR #3969)
+       - Build fixes (STR #3956)
+       - Group quota ACLs did not work with Kerberos (STR #3972)
+       - The IPP backend did not retry when a printer responded with
+         client-error-not-possible (STR #3963)
+       - PostScript PPDs with filters used the wrong command filter (STR #3973)
+       - The scheduler incorrectly used free() on a POSIX ACL value, which
+         could cause a crash (STR #3970)
+       - PPD files using the MacStandard encoding did not work.
+       - The web interface did not work on some platforms (STR #3902)
+       - The lpstat command would crash when then "-u" option was used by a
+         non-administrator (STR #3953)
+       - Japanese supply level reporting did not always work.
        - The DBUS notifier could crash (STR #3947)
        - Relaxed some of the page size checks in cupstestppd.
        - The ipptool program now reports attributes that are repeated within
index b7c55a1c8523ae69ef91ef3f8113a9d5791d5eaf..2d787597bdda1edcd128849e43b1f439043f290e 100644 (file)
@@ -1,13 +1,14 @@
-CHANGES-IPPTOOL.txt - 2011-10-04
+CHANGES-IPPTOOL.txt - 2011-10-05
 --------------------------------
 
 This file provides a list of changes to the ipptool binary distribution posted
 on cups.org.
 
 
-2011-10-04
+2011-10-05
 
        - Fixed a crasher bug that showed up on Windows.
+       - The IPP/1.1 test would hang if the initial Print-Job test failed.
        - Fixed a typo in the IPP/2.0 test.
 
 
index 8bca378935f08e33dfb3013dc978685ba21ad0d0..2261b5906869bdfa3f20c5065701706316cd8c6f 100644 (file)
@@ -1,8 +1,15 @@
-CHANGES.txt - 1.6b1 - 2011-08-30
+CHANGES.txt - 1.6b1 - 2011-11-03
 --------------------------------
 
 CHANGES IN CUPS V1.6b1
 
+       - CUPS no longer supports automatic remote printers or implicit classes
+         via the CUPS, LDAP, or SLP protocols (STR #3922, STR #3923)
+       - The PPD APIs are now deprecated and will be removed in a future
+         version of CUPS (STR #3927)
+       - The default IPP version for requests is now 2.0 (STR #3929)
+       - The IPP APIs no longer expose the ipp_t or ipp_attribute_t structures
+         and instead provide accessor functions (STR #3928)
        - The scheduler will no longer run programs with group write permission.
        - The PHP module has been removed (STR #3932)
        - The bannertops, commandtoescpx, commandtopclx, imagetops,
index b9a97a3b13f9baf7bc023819adcb6268772e8916..e59639e4a06ce22554d24996dd2cafe61296ae8b 100644 (file)
@@ -82,10 +82,8 @@ LIBCUPSIMAGE =       @LIBCUPSIMAGE@
 LIBCUPSMIME    =       @LIBCUPSMIME@
 LIBCUPSPPDC    =       @LIBCUPSPPDC@
 LIBCUPSSTATIC  =       @LIBCUPSSTATIC@
-LIBLDAP                =       @LIBLDAP@
 LIBMALLOC      =       @LIBMALLOC@
 LIBPAPER       =       @LIBPAPER@
-LIBSLP         =       @LIBSLP@
 LIBGSSAPI      =       @LIBGSSAPI@
 LIBUSB         =       @LIBUSB@
 LIBWRAP                =       @LIBWRAP@
index b7b21698ce4f6e23b9625ea40a29b1092fbc950d..6d61c6fba3114d45d92118965e47fec9c55166c4 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -246,13 +246,13 @@ debugcheck:       all unittests
 #
 
 apihelp:
-       for dir in cgi-bin cups filter driver ppdc scheduler; do\
+       for dir in cgi-bin cups filter ppdc scheduler; do\
                echo Generating API help in $$dir... ;\
                (cd $$dir; $(MAKE) $(MFLAGS) apihelp) || exit 1;\
        done
 
 framedhelp:
-       for dir in cgi-bin cups filter driver ppdc scheduler; do\
+       for dir in cgi-bin cups filter ppdc scheduler; do\
                echo Generating framed API help in $$dir... ;\
                (cd $$dir; $(MAKE) $(MFLAGS) framedhelp) || exit 1;\
        done
index 592b1e340a08ff9461c3ee48df194e1b0e8966a6..e46973ad090a2b6be7ef3fe0e8921c2cd08d15e1 100644 (file)
@@ -274,6 +274,7 @@ extern "C" {
 #define CUPS_TC_csUTF32                                1017
 #define CUPS_TC_csUTF32BE                      1018
 #define CUPS_TC_csUTF32LE                      1019
+#define CUPS_TC_csWindows31J                   2024
 
 
 /*
index 4ef67a4e2f2cdb8a84bb210fa301a324ba361240..99df346aea1da5d97eba1b4b6188aea10ebb683a 100644 (file)
@@ -1393,6 +1393,7 @@ main(int  argc,                           /* I - Number of command-line args */
         break;
 
       if (ipp_status == IPP_SERVICE_UNAVAILABLE ||
+          ipp_status == IPP_NOT_POSSIBLE ||
          ipp_status == IPP_PRINTER_BUSY)
       {
        _cupsLangPrintFilter(stderr, "INFO", _("The printer is busy."));
@@ -1550,6 +1551,7 @@ main(int  argc,                           /* I - Number of command-line args */
       copies_remaining --;
     }
     else if (ipp_status == IPP_SERVICE_UNAVAILABLE ||
+             ipp_status == IPP_NOT_POSSIBLE ||
             ipp_status == IPP_PRINTER_BUSY)
       continue;
     else
@@ -1622,6 +1624,7 @@ main(int  argc,                           /* I - Number of command-line args */
       if (ipp_status > IPP_OK_CONFLICT)
       {
        if (ipp_status != IPP_SERVICE_UNAVAILABLE &&
+           ipp_status != IPP_NOT_POSSIBLE &&
            ipp_status != IPP_PRINTER_BUSY)
        {
          ippDelete(response);
@@ -1669,7 +1672,9 @@ main(int  argc,                           /* I - Number of command-line args */
            break;
          }
        }
-       else
+       else if (ipp_status != IPP_SERVICE_UNAVAILABLE &&
+                ipp_status != IPP_NOT_POSSIBLE &&
+                ipp_status != IPP_PRINTER_BUSY)
        {
         /*
          * If the printer does not return a job-state attribute, it does not
index 92febb60215416fa862d6c9f534907c1b639aebc..b823520635d2f90a88e79e5d2b32242701abda9e 100644 (file)
@@ -801,6 +801,7 @@ backend_walk_cb(cups_snmp_t *packet,        /* I - SNMP packet */
           break;
 
       case CUPS_TC_csShiftJIS :
+      case CUPS_TC_csWindows31J : /* Close enough for our purposes */
          cupsCharsetToUTF8((cups_utf8_t *)supplies[i - 1].name,
                            (char *)packet->object_value.string.bytes,
                            sizeof(supplies[0].name), CUPS_JIS_X0213);
index b9963452b3a5e3599d8aa01927d2c7c462e8dd81..64a29bffd3a8e5f5d4be55f9ff31fd4231495ff7 100644 (file)
@@ -586,8 +586,7 @@ do_am_class(http_t *http,           /* I - HTTP connection */
     ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_ENUM, "printer-type",
                  CUPS_PRINTER_LOCAL);
     ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_ENUM, "printer-type-mask",
-                 CUPS_PRINTER_CLASS | CUPS_PRINTER_REMOTE |
-                     CUPS_PRINTER_IMPLICIT);
+                 CUPS_PRINTER_CLASS | CUPS_PRINTER_REMOTE);
 
    /*
     * Do the request and get back a response...
@@ -1560,8 +1559,6 @@ do_config_server(http_t *http)            /* I - HTTP connection */
     const char         *debug_logging, /* DEBUG_LOGGING value */
                        *remote_admin,  /* REMOTE_ADMIN value */
                        *remote_any,    /* REMOTE_ANY value */
-                       *remote_printers,
-                                       /* REMOTE_PRINTERS value */
                        *share_printers,/* SHARE_PRINTERS value */
                        *user_cancel_any,
                                        /* USER_CANCEL_ANY value */
@@ -1577,10 +1574,6 @@ do_config_server(http_t *http)           /* I - HTTP connection */
                                        /* MaxJobs value */
                        *max_log_size = NULL;
                                        /* MaxLogSize value */
-    char               local_protocols[255],
-                                       /* BrowseLocalProtocols */
-                       remote_protocols[255];
-                                       /* BrowseRemoteProtocols */
     const char         *current_browse_web_if,
                                        /* BrowseWebIF value */
                        *current_preserve_job_history,
@@ -1591,12 +1584,8 @@ do_config_server(http_t *http)           /* I - HTTP connection */
                                        /* MaxClients value */
                        *current_max_jobs,
                                        /* MaxJobs value */
-                       *current_max_log_size,
+                       *current_max_log_size;
                                        /* MaxLogSize value */
-                       *current_local_protocols,
-                                       /* BrowseLocalProtocols */
-                       *current_remote_protocols;
-                                       /* BrowseRemoteProtocols */
 #ifdef HAVE_GSSAPI
     char               default_auth_type[255];
                                        /* DefaultAuthType value */
@@ -1611,7 +1600,6 @@ do_config_server(http_t *http)            /* I - HTTP connection */
     debug_logging        = cgiGetVariable("DEBUG_LOGGING") ? "1" : "0";
     remote_admin         = cgiGetVariable("REMOTE_ADMIN") ? "1" : "0";
     remote_any           = cgiGetVariable("REMOTE_ANY") ? "1" : "0";
-    remote_printers      = cgiGetVariable("REMOTE_PRINTERS") ? "1" : "0";
     share_printers       = cgiGetVariable("SHARE_PRINTERS") ? "1" : "0";
     user_cancel_any      = cgiGetVariable("USER_CANCEL_ANY") ? "1" : "0";
 
@@ -1637,66 +1625,6 @@ do_config_server(http_t *http)           /* I - HTTP connection */
 
       if (!max_log_size || atof(max_log_size) <= 0.0)
        max_log_size = "1m";
-
-      if (cgiGetVariable("BROWSE_LOCAL_CUPS"))
-       strcpy(local_protocols, "cups");
-      else
-       local_protocols[0] = '\0';
-
-#ifdef HAVE_DNSSD
-      if (cgiGetVariable("BROWSE_LOCAL_DNSSD"))
-      {
-       if (local_protocols[0])
-         strcat(local_protocols, " dnssd");
-       else
-         strcat(local_protocols, "dnssd");
-      }
-#endif /* HAVE_DNSSD */
-
-#ifdef HAVE_LDAP
-      if (cgiGetVariable("BROWSE_LOCAL_LDAP"))
-      {
-       if (local_protocols[0])
-         strcat(local_protocols, " ldap");
-       else
-         strcat(local_protocols, "ldap");
-      }
-#endif /* HAVE_LDAP */
-
-#ifdef HAVE_LIBSLP
-      if (cgiGetVariable("BROWSE_LOCAL_SLP"))
-      {
-       if (local_protocols[0])
-         strcat(local_protocols, " slp");
-       else
-         strcat(local_protocols, "slp");
-      }
-#endif /* HAVE_SLP */
-
-      if (cgiGetVariable("BROWSE_REMOTE_CUPS"))
-       strcpy(remote_protocols, "cups");
-      else
-       remote_protocols[0] = '\0';
-
-#ifdef HAVE_LDAP
-      if (cgiGetVariable("BROWSE_REMOTE_LDAP"))
-      {
-       if (remote_protocols[0])
-         strcat(remote_protocols, " ldap");
-       else
-         strcat(remote_protocols, "ldap");
-      }
-#endif /* HAVE_LDAP */
-
-#ifdef HAVE_LIBSLP
-      if (cgiGetVariable("BROWSE_REMOTE_SLP"))
-      {
-       if (remote_protocols[0])
-         strcat(remote_protocols, " slp");
-       else
-         strcat(remote_protocols, "slp");
-      }
-#endif /* HAVE_SLP */
     }
 
    /*
@@ -1760,16 +1688,6 @@ do_config_server(http_t *http)           /* I - HTTP connection */
                                               settings)) == NULL)
       current_max_log_size = "1m";
 
-    if ((current_local_protocols = cupsGetOption("BrowseLocalProtocols",
-                                                 num_settings,
-                                               settings)) == NULL)
-      current_local_protocols = CUPS_DEFAULT_BROWSE_LOCAL_PROTOCOLS;
-
-    if ((current_remote_protocols = cupsGetOption("BrowseRemoteProtocols",
-                                                  num_settings,
-                                                 settings)) == NULL)
-      current_remote_protocols = CUPS_DEFAULT_BROWSE_REMOTE_PROTOCOLS;
-
    /*
     * See if the settings have changed...
     */
@@ -1780,8 +1698,6 @@ do_config_server(http_t *http)            /* I - HTTP connection */
                                                 num_settings, settings)) ||
              strcmp(remote_any, cupsGetOption(CUPS_SERVER_REMOTE_ANY,
                                               num_settings, settings)) ||
-             strcmp(remote_printers, cupsGetOption(CUPS_SERVER_REMOTE_PRINTERS,
-                                                   num_settings, settings)) ||
              strcmp(share_printers, cupsGetOption(CUPS_SERVER_SHARE_PRINTERS,
                                                   num_settings, settings)) ||
 #ifdef HAVE_GSSAPI
@@ -1793,9 +1709,7 @@ do_config_server(http_t *http)            /* I - HTTP connection */
                                                    num_settings, settings));
 
     if (advanced && !changed)
-      changed = _cups_strcasecmp(local_protocols, current_local_protocols) ||
-               _cups_strcasecmp(remote_protocols, current_remote_protocols) ||
-               _cups_strcasecmp(browse_web_if, current_browse_web_if) ||
+      changed = _cups_strcasecmp(browse_web_if, current_browse_web_if) ||
                _cups_strcasecmp(preserve_job_history, current_preserve_job_history) ||
                _cups_strcasecmp(preserve_job_files, current_preserve_job_files) ||
                _cups_strcasecmp(max_clients, current_max_clients) ||
@@ -1817,8 +1731,6 @@ do_config_server(http_t *http)            /* I - HTTP connection */
                                    remote_admin, num_settings, &settings);
       num_settings = cupsAddOption(CUPS_SERVER_REMOTE_ANY,
                                    remote_any, num_settings, &settings);
-      num_settings = cupsAddOption(CUPS_SERVER_REMOTE_PRINTERS,
-                                   remote_printers, num_settings, &settings);
       num_settings = cupsAddOption(CUPS_SERVER_SHARE_PRINTERS,
                                    share_printers, num_settings, &settings);
       num_settings = cupsAddOption(CUPS_SERVER_USER_CANCEL_ANY,
@@ -1834,12 +1746,6 @@ do_config_server(http_t *http)           /* I - HTTP connection */
         * Add advanced settings...
        */
 
-       if (_cups_strcasecmp(local_protocols, current_local_protocols))
-         num_settings = cupsAddOption("BrowseLocalProtocols", local_protocols,
-                                      num_settings, &settings);
-       if (_cups_strcasecmp(remote_protocols, current_remote_protocols))
-         num_settings = cupsAddOption("BrowseRemoteProtocols", remote_protocols,
-                                      num_settings, &settings);
        if (_cups_strcasecmp(browse_web_if, current_browse_web_if))
          num_settings = cupsAddOption("BrowseWebIF", browse_web_if,
                                       num_settings, &settings);
@@ -1878,7 +1784,8 @@ do_config_server(http_t *http)            /* I - HTTP connection */
       else
       {
         if (advanced)
-         cgiSetVariable("refresh_page", "5;URL=/admin/?OP=redirect&URL=/admin/?ADVANCEDSETTINGS=YES");
+         cgiSetVariable("refresh_page", "5;URL=/admin/?OP=redirect&"
+                                        "URL=/admin/?ADVANCEDSETTINGS=YES");
         else
          cgiSetVariable("refresh_page", "5;URL=/admin/?OP=redirect");
        cgiStartHTML(cgiText(_("Change Settings")));
@@ -2359,8 +2266,7 @@ do_export(http_t *http)                   /* I - HTTP connection */
                 "printer-type", 0);
 
   ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_ENUM,
-                "printer-type-mask", CUPS_PRINTER_CLASS | CUPS_PRINTER_REMOTE |
-                                    CUPS_PRINTER_IMPLICIT);
+                "printer-type-mask", CUPS_PRINTER_CLASS | CUPS_PRINTER_REMOTE);
 
   ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
                "requested-attributes", NULL, "printer-name");
@@ -2696,10 +2602,6 @@ do_menu(http_t *http)                    /* I - HTTP connection */
                            settings)) != NULL && atoi(val))
     cgiSetVariable("REMOTE_ANY", "CHECKED");
 
-  if ((val = cupsGetOption(CUPS_SERVER_REMOTE_PRINTERS, num_settings,
-                           settings)) != NULL && atoi(val))
-    cgiSetVariable("REMOTE_PRINTERS", "CHECKED");
-
   if ((val = cupsGetOption(CUPS_SERVER_SHARE_PRINTERS, num_settings,
                            settings)) != NULL && atoi(val))
     cgiSetVariable("SHARE_PRINTERS", "CHECKED");
@@ -2722,49 +2624,6 @@ do_menu(http_t *http)                    /* I - HTTP connection */
   cgiSetVariable("HAVE_DNSSD", "1");
 #endif /* HAVE_DNSSD */
 
-#ifdef HAVE_LDAP
-  cgiSetVariable("HAVE_LDAP", "1");
-#endif /* HAVE_LDAP */
-
-#ifdef HAVE_LIBSLP
-  cgiSetVariable("HAVE_LIBSLP", "1");
-#endif /* HAVE_LIBSLP */
-
-  if ((val = cupsGetOption("BrowseRemoteProtocols", num_settings,
-                           settings)) == NULL)
-    if ((val = cupsGetOption("BrowseProtocols", num_settings,
-                           settings)) == NULL)
-      val = CUPS_DEFAULT_BROWSE_REMOTE_PROTOCOLS;
-
-  if (strstr(val, "cups") || strstr(val, "CUPS"))
-    cgiSetVariable("BROWSE_REMOTE_CUPS", "CHECKED");
-
-  if (strstr(val, "ldap") || strstr(val, "LDAP"))
-    cgiSetVariable("BROWSE_REMOTE_LDAP", "CHECKED");
-
-  if (strstr(val, "slp") || strstr(val, "SLP"))
-    cgiSetVariable("BROWSE_REMOTE_SLP", "CHECKED");
-
-  if ((val = cupsGetOption("BrowseLocalProtocols", num_settings,
-                           settings)) == NULL)
-    if ((val = cupsGetOption("BrowseProtocols", num_settings,
-                           settings)) == NULL)
-      val = CUPS_DEFAULT_BROWSE_LOCAL_PROTOCOLS;
-
-  if (strstr(val, "cups") || strstr(val, "CUPS"))
-    cgiSetVariable("BROWSE_LOCAL_CUPS", "CHECKED");
-
-  if (strstr(val, "dnssd") || strstr(val, "DNSSD") ||
-      strstr(val, "dns-sd") || strstr(val, "DNS-SD") ||
-      strstr(val, "bonjour") || strstr(val, "BONJOUR"))
-    cgiSetVariable("BROWSE_LOCAL_DNSSD", "CHECKED");
-
-  if (strstr(val, "ldap") || strstr(val, "LDAP"))
-    cgiSetVariable("BROWSE_LOCAL_LDAP", "CHECKED");
-
-  if (strstr(val, "slp") || strstr(val, "SLP"))
-    cgiSetVariable("BROWSE_LOCAL_SLP", "CHECKED");
-
   if ((val = cupsGetOption("BrowseWebIF", num_settings,
                            settings)) == NULL)
     val = "No";
index fa9bb9b66cae4e9436bfe682daba331215563f65..412bdc39a00a47729106eeb0d77c2f00d5d46ef0 100644 (file)
@@ -3,7 +3,7 @@
  *
  *   Private CGI definitions for CUPS.
  *
- *   Copyright 2007-2010 by Apple Inc.
+ *   Copyright 2007-2011 by Apple Inc.
  *   Copyright 1997-2006 by Easy Software Products.
  *
  *   These coded instructions, statements, and computer programs are the
@@ -21,6 +21,7 @@
 #include <cups/debug-private.h>
 #include <cups/language-private.h>
 #include <cups/string-private.h>
+#include <cups/ipp-private.h>  /* TODO: Update so we don't need this */
 
 
 /*
index d7239434b6f3acd95b13d508d513ddbd2e558ed3..2417da8f83749ef0505a1c8e1c255d38a976cc76 100644 (file)
@@ -389,7 +389,17 @@ case $uname in
 
                dnl Check for sandbox/Seatbelt support
                if test $uversion -ge 100; then
-                   AC_CHECK_HEADER(sandbox.h,AC_DEFINE(HAVE_SANDBOX_H))
+                       AC_CHECK_HEADER(sandbox.h,AC_DEFINE(HAVE_SANDBOX_H))
+               fi
+               if test $uversion -ge 110; then
+                       # Broken public headers in 10.7...
+                       AC_MSG_CHECKING(for sandbox/private.h presence)
+                       if test -f /usr/local/include/sandbox/private.h; then
+                               AC_MSG_RESULT(yes)
+                       else
+                               AC_MSG_RESULT(no)
+                               AC_MSG_ERROR(Run 'sudo mkdir -p /usr/local/include/sandbox' and 'sudo touch /usr/local/include/sandbox/private.h' to build CUPS.)
+                       fi
                fi
 
                dnl Check for XPC support
index eebbb29bb71aaeedfeff908473cfcb9070016dbd..c223d8db05f9e54a7e0101598f784312e8a76a43 100644 (file)
@@ -64,7 +64,6 @@ AC_ARG_WITH(fatal_errors, [  --with-fatal-errors     set default FatalErrors val
 AC_SUBST(CUPS_FATAL_ERRORS)
 AC_DEFINE_UNQUOTED(CUPS_DEFAULT_FATAL_ERRORS, "$CUPS_FATAL_ERRORS")
 
-
 dnl Default LogLevel
 AC_ARG_WITH(log_level, [  --with-log-level        set default LogLevel value, default=warn],
        CUPS_LOG_LEVEL="$withval",
@@ -91,16 +90,16 @@ fi
 AC_SUBST(CUPS_BROWSING)
 
 dnl Default BrowseLocalProtocols
-AC_ARG_WITH(local_protocols, [  --with-local-protocols  set default BrowseLocalProtocols, default="CUPS"],
+AC_ARG_WITH(local_protocols, [  --with-local-protocols  set default BrowseLocalProtocols, default=""],
        default_local_protocols="$withval",
        default_local_protocols="default")
 
 if test x$with_local_protocols != xno; then
        if test "x$default_local_protocols" = "xdefault"; then
                if test "x$DNSSDLIBS" != "x"; then
-               CUPS_BROWSE_LOCAL_PROTOCOLS="CUPS dnssd"
-       else
-               CUPS_BROWSE_LOCAL_PROTOCOLS="CUPS"
+                       CUPS_BROWSE_LOCAL_PROTOCOLS="dnssd"
+               else
+                       CUPS_BROWSE_LOCAL_PROTOCOLS=""
                fi
        else
                CUPS_BROWSE_LOCAL_PROTOCOLS="$default_local_protocols"
@@ -113,41 +112,6 @@ AC_SUBST(CUPS_BROWSE_LOCAL_PROTOCOLS)
 AC_DEFINE_UNQUOTED(CUPS_DEFAULT_BROWSE_LOCAL_PROTOCOLS,
        "$CUPS_BROWSE_LOCAL_PROTOCOLS")
 
-dnl Default BrowseRemoteProtocols
-AC_ARG_WITH(remote_protocols, [  --with-remote-protocols set default BrowseRemoteProtocols, default="CUPS"],
-       default_remote_protocols="$withval",
-       default_remote_protocols="default")
-
-if test x$with_remote_protocols != xno; then
-       if test "x$default_remote_protocols" = "xdefault"; then
-               if test "$uname" = "Darwin" -a $uversion -ge 90; then
-                       CUPS_BROWSE_REMOTE_PROTOCOLS=""
-               else
-                       CUPS_BROWSE_REMOTE_PROTOCOLS="CUPS"
-               fi
-       else
-               CUPS_BROWSE_REMOTE_PROTOCOLS="$default_remote_protocols"
-       fi
-else
-       CUPS_BROWSE_REMOTE_PROTOCOLS=""
-fi
-
-AC_SUBST(CUPS_BROWSE_REMOTE_PROTOCOLS)
-AC_DEFINE_UNQUOTED(CUPS_DEFAULT_BROWSE_REMOTE_PROTOCOLS,
-       "$CUPS_BROWSE_REMOTE_PROTOCOLS")
-
-dnl Default BrowseShortNames
-AC_ARG_ENABLE(browse_short, [  --disable-browse-short-names
-                         disable BrowseShortNames by default])
-if test "x$enable_browse_short" = xno; then
-       CUPS_BROWSE_SHORT_NAMES="No"
-       AC_DEFINE_UNQUOTED(CUPS_DEFAULT_BROWSE_SHORT_NAMES, 0)
-else
-       CUPS_BROWSE_SHORT_NAMES="Yes"
-       AC_DEFINE_UNQUOTED(CUPS_DEFAULT_BROWSE_SHORT_NAMES, 1)
-fi
-AC_SUBST(CUPS_BROWSE_SHORT_NAMES)
-
 dnl Default DefaultShared
 AC_ARG_ENABLE(default_shared, [  --disable-default-shared
                          disable DefaultShared by default])
@@ -160,38 +124,6 @@ else
 fi
 AC_SUBST(CUPS_DEFAULT_SHARED)
 
-dnl Default ImplicitClasses
-AC_ARG_ENABLE(implicit, [  --disable-implicit-classes
-                          disable ImplicitClasses by default])
-if test "x$enable_implicit" = xno; then
-       CUPS_IMPLICIT_CLASSES="No"
-       AC_DEFINE_UNQUOTED(CUPS_DEFAULT_IMPLICIT_CLASSES, 0)
-else
-       CUPS_IMPLICIT_CLASSES="Yes"
-       AC_DEFINE_UNQUOTED(CUPS_DEFAULT_IMPLICIT_CLASSES, 1)
-fi
-AC_SUBST(CUPS_IMPLICIT_CLASSES)
-
-dnl Default UseNetworkDefault
-AC_ARG_ENABLE(use_network_default, [  --enable-use-network-default
-                          set UseNetworkDefault to Yes by default])
-if test "x$enable_use_network_default" != xno; then
-       AC_MSG_CHECKING(whether to use network default printers)
-       if test "x$enable_use_network_default" = xyes -o $uname != Darwin; then
-               CUPS_USE_NETWORK_DEFAULT="Yes"
-               AC_DEFINE_UNQUOTED(CUPS_DEFAULT_USE_NETWORK_DEFAULT, 1)
-               AC_MSG_RESULT(yes)
-       else
-               CUPS_USE_NETWORK_DEFAULT="No"
-               AC_DEFINE_UNQUOTED(CUPS_DEFAULT_USE_NETWORK_DEFAULT, 0)
-               AC_MSG_RESULT(no)
-       fi
-else
-       CUPS_USE_NETWORK_DEFAULT="No"
-       AC_DEFINE_UNQUOTED(CUPS_DEFAULT_USE_NETWORK_DEFAULT, 0)
-fi
-AC_SUBST(CUPS_USE_NETWORK_DEFAULT)
-
 dnl Determine the correct username and group for this OS...
 AC_ARG_WITH(cups_user, [  --with-cups-user        set default user for CUPS],
        CUPS_USER="$withval",
index 04977ee6493b94fd57229e05dd567cfb8baf26e7..cf7d58052492c79b0ded852b6808aae3564aa6af 100644 (file)
@@ -71,10 +71,45 @@ if test x$enable_gssapi != xno; then
        if test "x$LIBGSSAPI" != x; then
                AC_CHECK_HEADER(krb5.h, AC_DEFINE(HAVE_KRB5_H))
                if test -d /System/Library/Frameworks/GSS.framework; then
-                       AC_CHECK_HEADER(GSS/gssapi.h, AC_DEFINE(HAVE_GSS_GSSAPI_H))
-                       AC_CHECK_HEADER(GSS/gssapi_generic.h, AC_DEFINE(HAVE_GSSAPI_GENERIC_H))
-                       AC_CHECK_HEADER(GSS/gssapi_krb5.h, AC_DEFINE(HAVE_GSSAPI_KRB5_H))
-                       AC_CHECK_HEADER(GSS/gssapi_spi.h, AC_DEFINE(HAVE_GSS_GSSAPI_SPI_H))
+                       gssdir="/System/Library/Frameworks/GSS.framework"
+                       AC_MSG_CHECKING(for GSS/gssapi.h presence)
+                       if test -f $gssdir/Headers/gssapi.h; then
+                               AC_DEFINE(HAVE_GSS_GSSAPI_H)
+                               AC_MSG_RESULT(yes)
+                       else
+                               AC_MSG_RESULT(no)
+                       fi
+                       AC_MSG_CHECKING(for GSS/gssapi_generic.h presence)
+                       if test -f $gssdir/Headers/gssapi_generic.h; then
+                               AC_DEFINE(HAVE_GSSAPI_GENERIC_H)
+                               AC_MSG_RESULT(yes)
+                       else
+                               AC_MSG_RESULT(no)
+                       fi
+                       AC_MSG_CHECKING(for GSS/gssapi_krb5.h presence)
+                       if test -f $gssdir/Headers/gssapi_krb5.h; then
+                               AC_DEFINE(HAVE_GSSAPI_KRB5_H)
+                               AC_MSG_RESULT(yes)
+                       else
+                               AC_MSG_RESULT(no)
+                       fi
+                       AC_MSG_CHECKING(for GSS/gssapi_spi.h presence)
+                       if test -f $gssdir/PrivateHeaders/gssapi_spi.h; then
+                               AC_MSG_RESULT(yes)
+                               AC_MSG_CHECKING(for GSS/gssapi_spi.h usability)
+                               if test -s $gssdir/PrivateHeaders/gssapi_spi.h; then
+                                       AC_MSG_RESULT(yes)
+                                       AC_DEFINE(HAVE_GSS_GSSAPI_SPI_H)
+                               else
+                                       AC_MSG_RESULT(no)
+                               fi
+                       else
+                               AC_MSG_RESULT(no)
+                               if test $uversion -ge 110; then
+                                       # Broken public headers in 10.7...
+                                       AC_MSG_ERROR(Run 'sudo mkdir -p $gssdir/PrivateHeaders' and 'sudo touch $gssdir/PrivateHeaders/gssapi_spi.h' to build CUPS.)
+                               fi
+                       fi
                else
                        AC_CHECK_HEADER(gssapi.h, AC_DEFINE(HAVE_GSSAPI_H))
                        AC_CHECK_HEADER(gssapi/gssapi.h, AC_DEFINE(HAVE_GSSAPI_GSSAPI_H))
diff --git a/config-scripts/cups-ldap.m4 b/config-scripts/cups-ldap.m4
deleted file mode 100644 (file)
index 16c017c..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-dnl
-dnl "$Id: cups-ldap.m4 7800 2008-07-25 21:01:34Z mike $"
-dnl
-dnl   LDAP configuration stuff for CUPS.
-dnl
-dnl   Copyright 2007-2011 by Apple Inc.
-dnl   Copyright 2003-2006 by Easy Software Products, all rights reserved.
-dnl
-dnl   These coded instructions, statements, and computer programs are the
-dnl   property of Apple Inc. and are protected by Federal copyright
-dnl   law.  Distribution and use rights are outlined in the file "LICENSE.txt"
-dnl   which should have been included with this file.  If this file is
-dnl   file is missing or damaged, see the license at "http://www.cups.org/".
-dnl
-
-AC_ARG_ENABLE(ldap, [  --disable-ldap          disable LDAP support])
-AC_ARG_WITH(ldap-libs, [  --with-ldap-libs        set directory for LDAP library],
-    LDFLAGS="-L$withval $LDFLAGS"
-    DSOFLAGS="-L$withval $DSOFLAGS",)
-AC_ARG_WITH(ldap-includes, [  --with-ldap-includes    set directory for LDAP includes],
-    CFLAGS="-I$withval $CFLAGS"
-    CPPFLAGS="-I$withval $CPPFLAGS",)
-
-LIBLDAP=""
-
-if test x$enable_ldap != xno; then
-    AC_CHECK_HEADER(ldap.h, [
-       AC_CHECK_LIB(ldap, ldap_initialize,
-           AC_DEFINE(HAVE_LDAP)
-           AC_DEFINE(HAVE_OPENLDAP)
-           LIBLDAP="-lldap"
-           AC_CHECK_LIB(ldap, ldap_start_tls,
-               AC_DEFINE(HAVE_LDAP_SSL)),
-
-           AC_CHECK_LIB(ldap, ldap_init,
-               AC_DEFINE(HAVE_LDAP)
-               AC_DEFINE(HAVE_MOZILLA_LDAP)
-               LIBLDAP="-lldap"
-               AC_CHECK_HEADER(ldap_ssl.h, AC_DEFINE(HAVE_LDAP_SSL_H),,[#include <ldap.h>])
-               AC_CHECK_LIB(ldap, ldapssl_init,
-                   AC_DEFINE(HAVE_LDAP_SSL)))
-       )
-       AC_CHECK_LIB(ldap, ldap_set_rebind_proc, AC_DEFINE(HAVE_LDAP_REBIND_PROC))
-    ])
-fi
-
-AC_SUBST(LIBLDAP)
-
-
-dnl
-dnl End of "$Id: cups-ldap.m4 7800 2008-07-25 21:01:34Z mike $".
-dnl
diff --git a/config-scripts/cups-slp.m4 b/config-scripts/cups-slp.m4
deleted file mode 100644 (file)
index fdf1b43..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-dnl
-dnl "$Id: cups-slp.m4 7241 2008-01-22 22:34:52Z mike $"
-dnl
-dnl   OpenSLP configuration stuff for CUPS.
-dnl
-dnl   Copyright 2007-2011 by Apple Inc.
-dnl   Copyright 1997-2005 by Easy Software Products, all rights reserved.
-dnl
-dnl   These coded instructions, statements, and computer programs are the
-dnl   property of Apple Inc. and are protected by Federal copyright
-dnl   law.  Distribution and use rights are outlined in the file "LICENSE.txt"
-dnl   which should have been included with this file.  If this file is
-dnl   file is missing or damaged, see the license at "http://www.cups.org/".
-dnl
-
-AC_ARG_ENABLE(slp, [  --disable-slp           disable SLP support])
-AC_ARG_WITH(openslp-libs, [  --with-openslp-libs     set directory for OpenSLP library],
-    LDFLAGS="-L$withval $LDFLAGS"
-    DSOFLAGS="-L$withval $DSOFLAGS",)
-AC_ARG_WITH(openslp-includes, [  --with-openslp-includes set directory for OpenSLP includes],
-    CFLAGS="-I$withval $CFLAGS"
-    CPPFLAGS="-I$withval $CPPFLAGS",)
-
-LIBSLP=""
-
-if test x$enable_slp != xno; then
-    AC_CHECK_HEADER(slp.h,
-       AC_CHECK_LIB(slp, SLPOpen,
-            AC_DEFINE(HAVE_LIBSLP)
-           LIBSLP="-lslp"))
-fi
-
-AC_SUBST(LIBSLP)
-
-
-dnl
-dnl End of "$Id: cups-slp.m4 7241 2008-01-22 22:34:52Z mike $".
-dnl
index 188b7527f8c6e93a80b59fd34a47c1847d2547c8..a3500c9301964a6a5fcfd7155971c5a0a43c7bb4 100644 (file)
  */
 
 #define CUPS_DEFAULT_BROWSING  1
-#define CUPS_DEFAULT_BROWSE_LOCAL_PROTOCOLS    "CUPS"
-#define CUPS_DEFAULT_BROWSE_REMOTE_PROTOCOLS   "CUPS"
-#define CUPS_DEFAULT_BROWSE_SHORT_NAMES        1
+#define CUPS_DEFAULT_BROWSE_LOCAL_PROTOCOLS    ""
 #define CUPS_DEFAULT_DEFAULT_SHARED 1
-#define CUPS_DEFAULT_IMPLICIT_CLASSES  1
-#define CUPS_DEFAULT_USE_NETWORK_DEFAULT 1
 
 
 /*
index 60702956a2615923ed2a31ac42a510b01431c558..f35274b028da4047f7a445639d71d91ddd8a1047 100644 (file)
@@ -3,7 +3,7 @@ dnl "$Id: configure.in 7833 2008-08-04 20:55:13Z mike $"
 dnl
 dnl   Configuration script for CUPS.
 dnl
-dnl   Copyright 2007-2010 by Apple Inc.
+dnl   Copyright 2007-2011 by Apple Inc.
 dnl   Copyright 1997-2007 by Easy Software Products, all rights reserved.
 dnl
 dnl   These coded instructions, statements, and computer programs are the
@@ -27,9 +27,7 @@ sinclude(config-scripts/cups-compiler.m4)
 
 sinclude(config-scripts/cups-network.m4)
 sinclude(config-scripts/cups-poll.m4)
-sinclude(config-scripts/cups-slp.m4)
 sinclude(config-scripts/cups-gssapi.m4)
-sinclude(config-scripts/cups-ldap.m4)
 sinclude(config-scripts/cups-threads.m4)
 sinclude(config-scripts/cups-ssl.m4)
 sinclude(config-scripts/cups-pam.m4)
index 0924e144dbcf2ccc34cd4a8c2ec89e6a68818ed8..be6bd42997a04cb178439effbd60a8ac751b69b4 100644 (file)
@@ -586,7 +586,7 @@ apihelp:
                file.h file.c dir.h dir.c >../doc/help/api-filedir.html
        mxmldoc --tokens api-filedir.xml >../doc/help/api-filedir.tokens
        $(RM) api-filedir.xml
-       mxmldoc --section "Programming" --title "PPD API" \
+       mxmldoc --section "Programming" --title "PPD API (DEPRECATED)" \
                --css ../doc/cups-printable.css \
                --header api-ppd.header --intro api-ppd.shtml \
                api-ppd.xml \
@@ -638,7 +638,7 @@ framedhelp:
                --header api-filedir.header --intro api-filedir.shtml \
                file.h file.c dir.h dir.c
        mxmldoc --framed api-ppd \
-               --section "Programming" --title "PPD API" \
+               --section "Programming" --title "PPD API (DEPRECATED)" \
                --css ../doc/cups-printable.css \
                --header api-ppd.header --intro api-ppd.shtml \
                ppd.h attr.c conflicts.c custom.c emit.c localize.c mark.c \
index 04b8e8fd2b4b9d657b516fd4845bb89ed14414a0..ee6f47ea3ca32da546bc64b6c63e01c03147ec33 100644 (file)
@@ -970,8 +970,6 @@ cupsAdminGetServerSettings(
                remote_admin = 0,       /* Remote administration allowed? */
                remote_any = 0,         /* Remote access from anywhere allowed? */
                browsing = 1,           /* Browsing enabled? */
-               browse_allow = 1,       /* Browse address set? */
-               browse_address = 0,     /* Browse address set? */
                cancel_policy = 1,      /* Cancel-job policy set? */
                debug_logging = 0;      /* LogLevel debug set? */
     int                linenum = 0,            /* Line number in file */
@@ -1020,26 +1018,16 @@ cupsAdminGetServerSettings(
       }
       else if (!_cups_strcasecmp(line, "Browsing"))
       {
-       browsing = !_cups_strcasecmp(value, "yes") || !_cups_strcasecmp(value, "on") ||
+       browsing = !_cups_strcasecmp(value, "yes") ||
+                  !_cups_strcasecmp(value, "on") ||
                   !_cups_strcasecmp(value, "true");
       }
-      else if (!_cups_strcasecmp(line, "BrowseAddress"))
-      {
-       browse_address = 1;
-      }
-      else if (!_cups_strcasecmp(line, "BrowseAllow"))
-      {
-       browse_allow = 1;
-      }
-      else if (!_cups_strcasecmp(line, "BrowseOrder"))
-      {
-       browse_allow = !_cups_strncasecmp(value, "deny,", 5);
-      }
       else if (!_cups_strcasecmp(line, "LogLevel"))
       {
        debug_logging = !_cups_strncasecmp(value, "debug", 5);
       }
-      else if (!_cups_strcasecmp(line, "<Policy") && !_cups_strcasecmp(value, "default"))
+      else if (!_cups_strcasecmp(line, "<Policy") &&
+               !_cups_strcasecmp(value, "default"))
       {
        in_policy = 1;
       }
@@ -1063,7 +1051,8 @@ cupsAdminGetServerSettings(
          if (*valptr)
            *valptr++ = '\0';
 
-          if (!_cups_strcasecmp(value, "cancel-job") || !_cups_strcasecmp(value, "all"))
+          if (!_cups_strcasecmp(value, "cancel-job") ||
+              !_cups_strcasecmp(value, "all"))
          {
            in_cancel_job = 1;
            break;
@@ -1091,7 +1080,8 @@ cupsAdminGetServerSettings(
        in_location       = 0;
       }
       else if (!_cups_strcasecmp(line, "Allow") && value &&
-               _cups_strcasecmp(value, "localhost") && _cups_strcasecmp(value, "127.0.0.1")
+               _cups_strcasecmp(value, "localhost") &&
+               _cups_strcasecmp(value, "127.0.0.1")
 #ifdef AF_LOCAL
               && *value != '/'
 #endif /* AF_LOCAL */
@@ -1135,15 +1125,9 @@ cupsAdminGetServerSettings(
                                           cg->cupsd_num_settings,
                                           &(cg->cupsd_settings));
 
-    cg->cupsd_num_settings = cupsAddOption(CUPS_SERVER_REMOTE_PRINTERS,
-                                           (browsing && browse_allow) ?
-                                              "1" : "0",
-                                          cg->cupsd_num_settings,
-                                          &(cg->cupsd_settings));
-
     cg->cupsd_num_settings = cupsAddOption(CUPS_SERVER_SHARE_PRINTERS,
-                                           (remote_access && browsing &&
-                                           browse_address) ? "1" : "0",
+                                           (remote_access && browsing) ? "1" :
+                                                                         "0",
                                           cg->cupsd_num_settings,
                                           &(cg->cupsd_settings));
 
@@ -1204,8 +1188,7 @@ cupsAdminSetServerSettings(
                in_conf_location,       /* In the /admin/conf location? */
                in_root_location;       /* In the / location? */
   const char   *val;                   /* Setting value */
-  int          remote_printers,        /* Show remote printers */
-               share_printers,         /* Share local printers */
+  int          share_printers,         /* Share local printers */
                remote_admin,           /* Remote administration allowed? */
                remote_any,             /* Remote access from anywhere? */
                user_cancel_any,        /* Cancel-job policy set? */
@@ -1219,8 +1202,7 @@ cupsAdminSetServerSettings(
                wrote_root_location;    /* Wrote the / location? */
   int          indent;                 /* Indentation */
   int          cupsd_num_settings;     /* New number of settings */
-  int          old_remote_printers,    /* Show remote printers */
-               old_share_printers,     /* Share local printers */
+  int          old_share_printers,     /* Share local printers */
                old_remote_admin,       /* Remote administration allowed? */
                old_user_cancel_any,    /* Cancel-job policy set? */
                old_debug_logging;      /* LogLevel debug set? */
@@ -1294,15 +1276,6 @@ cupsAdminSetServerSettings(
   DEBUG_printf(("1cupsAdminSetServerSettings: old remote_any=%d",
                 remote_any));
 
-  if ((val = cupsGetOption(CUPS_SERVER_REMOTE_PRINTERS, cupsd_num_settings,
-                           cupsd_settings)) != NULL)
-    old_remote_printers = atoi(val);
-  else
-    old_remote_printers = 1;
-
-  DEBUG_printf(("1cupsAdminSetServerSettings: old remote_printers=%d",
-                old_remote_printers));
-
   if ((val = cupsGetOption(CUPS_SERVER_SHARE_PRINTERS, cupsd_num_settings,
                            cupsd_settings)) != NULL)
     old_share_printers = atoi(val);
@@ -1374,26 +1347,6 @@ cupsAdminSetServerSettings(
   DEBUG_printf(("1cupsAdminSetServerSettings: remote_admin=%d",
                 remote_admin));
 
-  if ((val = cupsGetOption(CUPS_SERVER_REMOTE_PRINTERS, num_settings,
-                           settings)) != NULL)
-  {
-    remote_printers = atoi(val);
-
-    if (remote_printers == old_remote_printers)
-    {
-     /*
-      * No change to this setting...
-      */
-
-      remote_printers = -1;
-    }
-  }
-  else
-    remote_printers = -1;
-
-  DEBUG_printf(("1cupsAdminSetServerSettings: remote_printers=%d",
-                remote_printers));
-
   if ((val = cupsGetOption(CUPS_SERVER_SHARE_PRINTERS, num_settings,
                            settings)) != NULL)
   {
@@ -1517,80 +1470,33 @@ cupsAdminSetServerSettings(
         cupsFilePrintf(temp, "Listen %s\n", value);
     }
     else if ((!_cups_strcasecmp(line, "Browsing") ||
-              !_cups_strcasecmp(line, "BrowseAddress") ||
-              !_cups_strcasecmp(line, "BrowseAllow") ||
-              !_cups_strcasecmp(line, "BrowseDeny") ||
-              !_cups_strcasecmp(line, "BrowseLocalProtocols") ||
-              !_cups_strcasecmp(line, "BrowseRemoteProtocols") ||
-              !_cups_strcasecmp(line, "BrowseOrder")) &&
-            (remote_printers >= 0 || share_printers >= 0))
+              !_cups_strcasecmp(line, "BrowseLocalProtocols")) &&
+            share_printers >= 0)
     {
       if (!wrote_browsing)
       {
-       int new_remote_printers = (remote_printers > 0 ||
-                                  (remote_printers == -1 &&
-                                   old_remote_printers > 0));
        int new_share_printers = (share_printers > 0 ||
                                  (share_printers == -1 &&
                                   old_share_printers > 0));
 
         wrote_browsing = 1;
 
-        if (new_remote_printers || new_share_printers)
+        if (new_share_printers)
        {
          const char *localp = cupsGetOption("BrowseLocalProtocols",
                                             num_settings, settings);
-         const char *remotep = cupsGetOption("BrowseRemoteProtocols",
-                                             num_settings, settings);
 
           if (!localp || !localp[0])
            localp = cupsGetOption("BrowseLocalProtocols", cupsd_num_settings,
                                   cupsd_settings);
 
-          if (!remotep)
-           remotep = cupsGetOption("BrowseRemoteProtocols", cupsd_num_settings,
-                                   cupsd_settings);
-
-         if (new_remote_printers && new_share_printers)
-           cupsFilePuts(temp,
-                        "# Enable printer sharing and shared printers.\n");
-         else if (new_remote_printers)
-           cupsFilePuts(temp,
-                        "# Show shared printers on the local network.\n");
-         else
-           cupsFilePuts(temp,
-                        "# Share local printers on the local network.\n");
-
+         cupsFilePuts(temp, "# Share local printers on the local network.\n");
          cupsFilePuts(temp, "Browsing On\n");
-         cupsFilePuts(temp, "BrowseOrder allow,deny\n");
-
-         if (new_remote_printers)
-         {
-           cupsFilePuts(temp, "BrowseAllow all\n");
-
-           if (!remotep)
-             remotep = CUPS_DEFAULT_BROWSE_REMOTE_PROTOCOLS;
-
-           cupsFilePrintf(temp, "BrowseRemoteProtocols %s\n", remotep);
-          }
-         else
-           cupsFilePuts(temp, "BrowseRemoteProtocols\n");
 
-         cupsd_num_settings = cupsAddOption("BrowseRemoteProtocols", remotep,
-                                            cupsd_num_settings,
-                                            &cupsd_settings);
+         if (!localp)
+           localp = CUPS_DEFAULT_BROWSE_LOCAL_PROTOCOLS;
 
-         if (new_share_printers)
-         {
-           cupsFilePuts(temp, "BrowseAddress @LOCAL\n");
-
-           if (!localp)
-             localp = CUPS_DEFAULT_BROWSE_LOCAL_PROTOCOLS;
-
-           cupsFilePrintf(temp, "BrowseLocalProtocols %s\n", localp);
-         }
-         else
-           cupsFilePuts(temp, "BrowseLocalProtocols\n");
+         cupsFilePrintf(temp, "BrowseLocalProtocols %s\n", localp);
 
          cupsd_num_settings = cupsAddOption("BrowseLocalProtocols", localp,
                                             cupsd_num_settings,
@@ -1598,8 +1504,7 @@ cupsAdminSetServerSettings(
         }
        else
        {
-         cupsFilePuts(temp,
-                      "# Disable printer sharing and shared printers.\n");
+         cupsFilePuts(temp, "# Disable printer sharing.\n");
          cupsFilePuts(temp, "Browsing Off\n");
        }
       }
@@ -1865,25 +1770,12 @@ cupsAdminSetServerSettings(
   * Write any missing info...
   */
 
-  if (!wrote_browsing && (remote_printers >= 0 || share_printers >= 0))
+  if (!wrote_browsing && share_printers >= 0)
   {
-    if (remote_printers > 0 || share_printers > 0)
+    if (share_printers > 0)
     {
-      if (remote_printers > 0 && share_printers > 0)
-       cupsFilePuts(temp, "# Enable printer sharing and shared printers.\n");
-      else if (remote_printers > 0)
-       cupsFilePuts(temp, "# Show shared printers on the local network.\n");
-      else
-       cupsFilePuts(temp, "# Share local printers on the local network.\n");
-
+      cupsFilePuts(temp, "# Share local printers on the local network.\n");
       cupsFilePuts(temp, "Browsing On\n");
-      cupsFilePuts(temp, "BrowseOrder allow,deny\n");
-
-      if (remote_printers > 0)
-       cupsFilePuts(temp, "BrowseAllow all\n");
-
-      if (share_printers > 0)
-       cupsFilePuts(temp, "BrowseAddress @LOCAL\n");
     }
     else
     {
@@ -2090,15 +1982,6 @@ cupsAdminSetServerSettings(
                                        remote_any ? "1" : "0",
                                       cupsd_num_settings, &cupsd_settings);
 
-    if (remote_printers >= 0)
-      cupsd_num_settings = cupsAddOption(CUPS_SERVER_REMOTE_PRINTERS,
-                                        remote_printers ? "1" : "0",
-                                        cupsd_num_settings, &cupsd_settings);
-    else
-      cupsd_num_settings = cupsAddOption(CUPS_SERVER_REMOTE_PRINTERS,
-                                        old_remote_printers ? "1" : "0",
-                                        cupsd_num_settings, &cupsd_settings);
-
     if (share_printers >= 0)
       cupsd_num_settings = cupsAddOption(CUPS_SERVER_SHARE_PRINTERS,
                                         share_printers ? "1" : "0",
index f056916779c41026a564870f8a59537ea92bd4b3..14c681b16728d3b738324d11997a0ab3d5d28689 100644 (file)
@@ -3,7 +3,7 @@
  *
  *   Administration utility API definitions for CUPS.
  *
- *   Copyright 2007-2010 by Apple Inc.
+ *   Copyright 2007-2011 by Apple Inc.
  *   Copyright 2001-2007 by Easy Software Products.
  *
  *   These coded instructions, statements, and computer programs are the
@@ -42,7 +42,7 @@ extern "C" {
 #  define CUPS_SERVER_DEBUG_LOGGING    "_debug_logging"
 #  define CUPS_SERVER_REMOTE_ADMIN     "_remote_admin"
 #  define CUPS_SERVER_REMOTE_ANY       "_remote_any"
-#  define CUPS_SERVER_REMOTE_PRINTERS  "_remote_printers"
+/*#  define CUPS_SERVER_REMOTE_PRINTERS        "_remote_printers"*/
 #  define CUPS_SERVER_SHARE_PRINTERS   "_share_printers"
 #  define CUPS_SERVER_USER_CANCEL_ANY  "_user_cancel_any"
 
index 9809c86989e6a5905c6d0ebd97401be18148db5e..9eae26b48d559cea3463e3a7ca712c64c5ac0caf 100644 (file)
@@ -12,7 +12,9 @@
   file is missing or damaged, see the license at "http://www.cups.org/".
 -->
 
-<h1 class='title'>PPD API</h1>
+<h1 class='title'>PPD API (DEPRECATED)</h1>
+
+<blockquote>The PPD API is deprecated starting in CUPS 1.6. Please use the new Job Ticket APIs in the <a href="api-cups.html">CUPS API</a> documentation. These functions will be removed in a future release of CUPS.</blockquote>
 
 <div class='summary'><table summary='General Information'>
 <thead>
index ade717cafaa0abd1fc6c9ed6aab1966bbb173dfc..a8ecc095c8b61cf0d2858726d718535623fcf88c 100644 (file)
@@ -15,6 +15,8 @@
 
 <h2 class='title'><a name='OVERVIEW'>Overview</a></h2>
 
+<blockquote>The PPD API is deprecated starting in CUPS 1.6. Please use the new Job Ticket APIs in the <a href="api-cups.html">CUPS API</a> documentation. These functions will be removed in a future release of CUPS.</blockquote>
+
 <p>The CUPS PPD API provides read-only access the data in PostScript Printer
 Description ("PPD") files which are used for all printers with a driver. With
 it you can obtain the data necessary to display printer options to users, mark
index 1351581e067e678fc361462172f0046f37aebe7f..bea62b797a6e6163b9a2e486035365dc59053765 100644 (file)
@@ -65,6 +65,8 @@ extern const char *cssmErrorString(int error);
 #    ifdef HAVE_GSS_GSSAPI_SPI_H
 #      include <GSS/gssapi_spi.h>
 #    else
+#      define GSS_AUTH_IDENTITY_TYPE_1 1
+#      define gss_acquire_cred_ex_f __ApplePrivate_gss_acquire_cred_ex_f
 typedef struct gss_auth_identity
 {
   uint32_t type;
index 0a123c72898fd48fc3102b7f229868a9114414b2..cb82ddfc0b1d487b8beb789314d1b20163af22c5 100644 (file)
@@ -97,7 +97,7 @@ enum cups_ptype_e                     /**** Printer type/capability bit constants ****/
   CUPS_PRINTER_MEDIUM = 0x2000,                /* Can do Tabloid/B/C/A3/A2 */
   CUPS_PRINTER_LARGE = 0x4000,         /* Can do D/E/A1/A0 */
   CUPS_PRINTER_VARIABLE = 0x8000,      /* Can do variable sizes */
-  CUPS_PRINTER_IMPLICIT = 0x10000,     /* Implicit class */
+  CUPS_PRINTER_IMPLICIT = 0x10000,     /* Implicit class @private@ @since Deprecated@ */
   CUPS_PRINTER_DEFAULT = 0x20000,      /* Default printer on network */
   CUPS_PRINTER_FAX = 0x40000,          /* Fax queue */
   CUPS_PRINTER_REJECTING = 0x80000,    /* Printer is rejecting jobs */
@@ -105,7 +105,7 @@ enum cups_ptype_e                   /**** Printer type/capability bit constants ****/
   CUPS_PRINTER_NOT_SHARED = 0x200000,  /* Printer is not shared @since CUPS 1.2/Mac OS X 10.5@ */
   CUPS_PRINTER_AUTHENTICATED = 0x400000,/* Printer requires authentication @since CUPS 1.2/Mac OS X 10.5@ */
   CUPS_PRINTER_COMMANDS = 0x800000,    /* Printer supports maintenance commands @since CUPS 1.2/Mac OS X 10.5@ */
-  CUPS_PRINTER_DISCOVERED = 0x1000000, /* Printer was automatically discovered and added @since CUPS 1.3/Mac OS X 10.5@ */
+  CUPS_PRINTER_DISCOVERED = 0x1000000, /* Printer was automatically discovered and added @private@ @since Deprecated@ */
   CUPS_PRINTER_SCANNER = 0x2000000,    /* Scanner-only device @since CUPS 1.4/Mac OS X 10.6@ */
   CUPS_PRINTER_MFP = 0x4000000,                /* Printer with scanning capabilities @since CUPS 1.4/Mac OS X 10.6@ */
   CUPS_PRINTER_OPTIONS = 0x6fffc       /* ~(CLASS | REMOTE | IMPLICIT | DEFAULT | FAX | REJECTING | DELETE | NOT_SHARED | AUTHENTICATED | COMMANDS | DISCOVERED) @private@ */
index 0f2dd38cf8822d71f71f6e2f5eb628060c0f79f5..e2c09223272db2bb8a2033569d3c9ca387d496d7 100644 (file)
@@ -343,7 +343,8 @@ cupsEncodeOptions2(
     * Allocate memory for the attribute values...
     */
 
-    if ((attr = _ippAddAttr(ipp, count)) == NULL)
+    if ((attr = ippAddStrings(ipp, group_tag, value_tag, option->name, count,
+                              NULL, NULL)) == NULL)
     {
      /*
       * Ran out of memory!
@@ -353,19 +354,6 @@ cupsEncodeOptions2(
       return;
     }
 
-   /*
-    * Now figure out what type of value we have...
-    */
-
-    attr->group_tag = group_tag;
-    attr->value_tag = value_tag;
-
-   /*
-    * Copy the name over...
-    */
-
-    attr->name = _cupsStrAlloc(option->name);
-
     if (count > 1)
     {
      /*
index 160a09d07cc4166cf865da065a2d975a51077de1..2ea99bee1da51dfa73b2777b4f26c3767f2ce6fa 100644 (file)
  *
  * Contents:
  *
- *   httpAddCredential()       - Allocates and adds a single credential to an
- *                               array.
- *   _httpBIOMethods()         - Get the OpenSSL BIO methods for HTTP
- *                               connections.
- *   httpBlocking()            - Set blocking/non-blocking behavior on a
- *                               connection.
- *   httpCheck()               - Check to see if there is a pending response
- *                               from the server.
- *   httpClearCookie()         - Clear the cookie value(s).
- *   httpClearFields()         - Clear HTTP request fields.
- *   httpClose()               - Close an HTTP connection.
- *   httpConnect()             - Connect to a HTTP server.
- *   httpConnectEncrypt()      - Connect to a HTTP server using encryption.
- *   httpCopyCredentials()     - Copy the credentials associated with an
- *                               encrypted connection.
- *   _httpCreate()             - Create an unconnected HTTP connection.
- *   _httpCreateCredentials()  - Create credentials in the internal format.
- *   httpDelete()              - Send a DELETE request to the server.
- *   _httpDisconnect()         - Disconnect a HTTP connection.
- *   httpEncryption()          - Set the required encryption on the link.
- *   httpError()               - Get the last error on a connection.
- *   httpFlush()               - Flush data from a HTTP connection.
- *   httpFlushWrite()          - Flush data in write buffer.
- *   _httpFreeCredentials()    - Free internal credentials.
- *   httpFreeCredentials()     - Free an array of credentials.
- *   httpGet()                 - Send a GET request to the server.
- *   httpGetAuthString()       - Get the current authorization string.
- *   httpGetBlocking()         - Get the blocking/non-block state of a
- *                               connection.
- *   httpGetCookie()           - Get any cookie data from the response.
- *   httpGetFd()               - Get the file descriptor associated with a
- *                               connection.
- *   httpGetField()            - Get a field value from a request/response.
- *   httpGetLength()           - Get the amount of data remaining from the
- *                               content-length or transfer-encoding fields.
- *   httpGetLength2()          - Get the amount of data remaining from the
- *                               content-length or transfer-encoding fields.
- *   httpGetStatus()           - Get the status of the last HTTP request.
- *   httpGetSubField()         - Get a sub-field value.
- *   httpGetSubField2()        - Get a sub-field value.
- *   httpGets()                - Get a line of text from a HTTP connection.
- *   httpHead()                - Send a HEAD request to the server.
- *   httpInitialize()          - Initialize the HTTP interface library and set
- *                               the default HTTP proxy (if any).
- *   httpOptions()             - Send an OPTIONS request to the server.
- *   _httpPeek()               - Peek at data from a HTTP connection.
- *   httpPost()                - Send a POST request to the server.
- *   httpPrintf()              - Print a formatted string to a HTTP connection.
- *   httpPut()                 - Send a PUT request to the server.
- *   httpRead()                - Read data from a HTTP connection.
- *   httpRead2()               - Read data from a HTTP connection.
- *   _httpReadCDSA()           - Read function for the CDSA library.
- *   _httpReadGNUTLS()         - Read function for the GNU TLS library.
- *   httpReconnect()           - Reconnect to a HTTP server.
- *   httpSetAuthString()       - Set the current authorization string.
- *   httpSetCredentials()      - Set the credentials associated with an
- *                               encrypted connection.
- *   httpSetCookie()           - Set the cookie value(s).
- *   httpSetExpect()           - Set the Expect: header in a request.
- *   httpSetField()            - Set the value of an HTTP header.
- *   httpSetLength()           - Set the content-length and content-encoding.
- *   httpSetTimeout()          - Set read/write timeouts and an optional
- *                               callback.
- *   httpTrace()               - Send an TRACE request to the server.
- *   _httpUpdate()             - Update the current HTTP status for incoming
- *                               data.
- *   httpUpdate()              - Update the current HTTP state for incoming
- *                               data.
- *   _httpWait()               - Wait for data available on a connection (no
- *                               flush).
- *   httpWait()                - Wait for data available on a connection.
- *   httpWrite()               - Write data to a HTTP connection.
- *   httpWrite2()              - Write data to a HTTP connection.
- *   _httpWriteCDSA()          - Write function for the CDSA library.
- *   _httpWriteGNUTLS()        - Write function for the GNU TLS library.
- *   http_bio_ctrl()           - Control the HTTP connection.
- *   http_bio_free()           - Free OpenSSL data.
- *   http_bio_new()            - Initialize an OpenSSL BIO structure.
- *   http_bio_puts()           - Send a string for OpenSSL.
- *   http_bio_read()           - Read data for OpenSSL.
- *   http_bio_write()          - Write data for OpenSSL.
- *   http_debug_hex()          - Do a hex dump of a buffer.
- *   http_field()              - Return the field index for a field name.
- *   http_read_ssl()           - Read from a SSL/TLS connection.
- *   http_locking_cb()         - Lock/unlock a thread's mutex.
- *   http_send()               - Send a request with all fields and the trailing
- *                               blank line.
- *   http_set_credentials()    - Set the SSL/TLS credentials.
- *   http_set_timeout()        - Set the socket timeout values.
- *   http_set_wait()           - Set the default wait value for reads.
- *   http_setup_ssl()          - Set up SSL/TLS support on a connection.
- *   http_shutdown_ssl()       - Shut down SSL/TLS on a connection.
- *   http_threadid_cb()        - Return the current thread ID.
- *   http_upgrade()            - Force upgrade to TLS encryption.
- *   http_write()              - Write a buffer to a HTTP connection.
- *   http_write_chunk()        - Write a chunked buffer.
- *   http_write_ssl()          - Write to a SSL/TLS connection.
+ *   httpAddCredential()      - Allocates and adds a single credential to an
+ *                             array.
+ *   _httpBIOMethods()       - Get the OpenSSL BIO methods for HTTP
+ *                             connections.
+ *   httpBlocking()          - Set blocking/non-blocking behavior on a
+ *                             connection.
+ *   httpCheck()             - Check to see if there is a pending response
+ *                             from the server.
+ *   httpClearCookie()       - Clear the cookie value(s).
+ *   httpClearFields()       - Clear HTTP request fields.
+ *   httpClose()             - Close an HTTP connection.
+ *   httpConnect()           - Connect to a HTTP server.
+ *   httpConnectEncrypt()     - Connect to a HTTP server using encryption.
+ *   httpCopyCredentials()    - Copy the credentials associated with an
+ *                             encrypted connection.
+ *   _httpCreate()           - Create an unconnected HTTP connection.
+ *   _httpCreateCredentials() - Create credentials in the internal format.
+ *   httpDelete()            - Send a DELETE request to the server.
+ *   _httpDisconnect()       - Disconnect a HTTP connection.
+ *   httpEncryption()        - Set the required encryption on the link.
+ *   httpError()             - Get the last error on a connection.
+ *   httpFlush()             - Flush data from a HTTP connection.
+ *   httpFlushWrite()        - Flush data in write buffer.
+ *   _httpFreeCredentials()   - Free internal credentials.
+ *   httpFreeCredentials()    - Free an array of credentials.
+ *   httpGet()               - Send a GET request to the server.
+ *   httpGetAuthString()      - Get the current authorization string.
+ *   httpGetBlocking()       - Get the blocking/non-block state of a
+ *                             connection.
+ *   httpGetCookie()         - Get any cookie data from the response.
+ *   httpGetFd()             - Get the file descriptor associated with a
+ *                             connection.
+ *   httpGetField()          - Get a field value from a request/response.
+ *   httpGetLength()         - Get the amount of data remaining from the
+ *                             content-length or transfer-encoding fields.
+ *   httpGetLength2()        - Get the amount of data remaining from the
+ *                             content-length or transfer-encoding fields.
+ *   httpGets()              - Get a line of text from a HTTP connection.
+ *   httpGetState()          - Get the current state of the HTTP request.
+ *   httpGetStatus()         - Get the status of the last HTTP request.
+ *   httpGetSubField()       - Get a sub-field value.
+ *   httpGetSubField2()       - Get a sub-field value.
+ *   httpGetVersion()        - Get the HTTP version at the other end.
+ *   httpHead()              - Send a HEAD request to the server.
+ *   httpInitialize()        - Initialize the HTTP interface library and set
+ *                             the default HTTP proxy (if any).
+ *   httpOptions()           - Send an OPTIONS request to the server.
+ *   _httpPeek()             - Peek at data from a HTTP connection.
+ *   httpPost()              - Send a POST request to the server.
+ *   httpPrintf()            - Print a formatted string to a HTTP connection.
+ *   httpPut()               - Send a PUT request to the server.
+ *   httpRead()              - Read data from a HTTP connection.
+ *   httpRead2()             - Read data from a HTTP connection.
+ *   _httpReadCDSA()         - Read function for the CDSA library.
+ *   _httpReadGNUTLS()       - Read function for the GNU TLS library.
+ *   httpReconnect()         - Reconnect to a HTTP server.
+ *   httpSetAuthString()      - Set the current authorization string.
+ *   httpSetCredentials()     - Set the credentials associated with an
+ *                             encrypted connection.
+ *   httpSetCookie()         - Set the cookie value(s).
+ *   httpSetExpect()         - Set the Expect: header in a request.
+ *   httpSetField()          - Set the value of an HTTP header.
+ *   httpSetLength()         - Set the content-length and content-encoding.
+ *   httpSetTimeout()        - Set read/write timeouts and an optional
+ *                             callback.
+ *   httpTrace()             - Send an TRACE request to the server.
+ *   _httpUpdate()           - Update the current HTTP status for incoming
+ *                             data.
+ *   httpUpdate()            - Update the current HTTP state for incoming
+ *                             data.
+ *   _httpWait()             - Wait for data available on a connection (no
+ *                             flush).
+ *   httpWait()              - Wait for data available on a connection.
+ *   httpWrite()             - Write data to a HTTP connection.
+ *   httpWrite2()            - Write data to a HTTP connection.
+ *   _httpWriteCDSA()        - Write function for the CDSA library.
+ *   _httpWriteGNUTLS()       - Write function for the GNU TLS library.
+ *   http_bio_ctrl()         - Control the HTTP connection.
+ *   http_bio_free()         - Free OpenSSL data.
+ *   http_bio_new()          - Initialize an OpenSSL BIO structure.
+ *   http_bio_puts()         - Send a string for OpenSSL.
+ *   http_bio_read()         - Read data for OpenSSL.
+ *   http_bio_write()        - Write data for OpenSSL.
+ *   http_debug_hex()        - Do a hex dump of a buffer.
+ *   http_field()            - Return the field index for a field name.
+ *   http_read_ssl()         - Read from a SSL/TLS connection.
+ *   http_send()             - Send a request with all fields and the trailing
+ *                             blank line.
+ *   http_set_credentials()   - Set the SSL/TLS credentials.
+ *   http_set_timeout()       - Set the socket timeout values.
+ *   http_set_wait()         - Set the default wait value for reads.
+ *   http_setup_ssl()        - Set up SSL/TLS support on a connection.
+ *   http_shutdown_ssl()      - Shut down SSL/TLS on a connection.
+ *   http_upgrade()          - Force upgrade to TLS encryption.
+ *   http_write()            - Write a buffer to a HTTP connection.
+ *   http_write_chunk()       - Write a chunked buffer.
+ *   http_write_ssl()        - Write to a SSL/TLS connection.
  */
 
 /*
@@ -1116,167 +1116,6 @@ httpGetLength2(http_t *http)            /* I - Connection to server */
 }
 
 
-/*
- * 'httpGetStatus()' - Get the status of the last HTTP request.
- *
- * @since CUPS 1.2/Mac OS X 10.5@
- */
-
-http_status_t                          /* O - HTTP status */
-httpGetStatus(http_t *http)            /* I - Connection to server */
-{
-  return (http ? http->status : HTTP_ERROR);
-}
-
-
-/*
- * 'httpGetSubField()' - Get a sub-field value.
- *
- * @deprecated@
- */
-
-char *                                 /* O - Value or NULL */
-httpGetSubField(http_t       *http,    /* I - Connection to server */
-                http_field_t field,    /* I - Field index */
-                const char   *name,    /* I - Name of sub-field */
-               char         *value)    /* O - Value string */
-{
-  return (httpGetSubField2(http, field, name, value, HTTP_MAX_VALUE));
-}
-
-
-/*
- * 'httpGetSubField2()' - Get a sub-field value.
- *
- * @since CUPS 1.2/Mac OS X 10.5@
- */
-
-char *                                 /* O - Value or NULL */
-httpGetSubField2(http_t       *http,   /* I - Connection to server */
-                 http_field_t field,   /* I - Field index */
-                 const char   *name,   /* I - Name of sub-field */
-                char         *value,   /* O - Value string */
-                int          valuelen) /* I - Size of value buffer */
-{
-  const char   *fptr;                  /* Pointer into field */
-  char         temp[HTTP_MAX_VALUE],   /* Temporary buffer for name */
-               *ptr,                   /* Pointer into string buffer */
-               *end;                   /* End of value buffer */
-
-  DEBUG_printf(("2httpGetSubField2(http=%p, field=%d, name=\"%s\", value=%p, "
-                "valuelen=%d)", http, field, name, value, valuelen));
-
-  if (!http || !name || !value || valuelen < 2 ||
-      field <= HTTP_FIELD_UNKNOWN || field >= HTTP_FIELD_MAX)
-    return (NULL);
-
-  end = value + valuelen - 1;
-
-  for (fptr = http->fields[field]; *fptr;)
-  {
-   /*
-    * Skip leading whitespace...
-    */
-
-    while (_cups_isspace(*fptr))
-      fptr ++;
-
-    if (*fptr == ',')
-    {
-      fptr ++;
-      continue;
-    }
-
-   /*
-    * Get the sub-field name...
-    */
-
-    for (ptr = temp;
-         *fptr && *fptr != '=' && !_cups_isspace(*fptr) &&
-            ptr < (temp + sizeof(temp) - 1);
-         *ptr++ = *fptr++);
-
-    *ptr = '\0';
-
-    DEBUG_printf(("4httpGetSubField2: name=\"%s\"", temp));
-
-   /*
-    * Skip trailing chars up to the '='...
-    */
-
-    while (_cups_isspace(*fptr))
-      fptr ++;
-
-    if (!*fptr)
-      break;
-
-    if (*fptr != '=')
-      continue;
-
-   /*
-    * Skip = and leading whitespace...
-    */
-
-    fptr ++;
-
-    while (_cups_isspace(*fptr))
-      fptr ++;
-
-    if (*fptr == '\"')
-    {
-     /*
-      * Read quoted string...
-      */
-
-      for (ptr = value, fptr ++;
-           *fptr && *fptr != '\"' && ptr < end;
-          *ptr++ = *fptr++);
-
-      *ptr = '\0';
-
-      while (*fptr && *fptr != '\"')
-        fptr ++;
-
-      if (*fptr)
-        fptr ++;
-    }
-    else
-    {
-     /*
-      * Read unquoted string...
-      */
-
-      for (ptr = value;
-           *fptr && !_cups_isspace(*fptr) && *fptr != ',' && ptr < end;
-          *ptr++ = *fptr++);
-
-      *ptr = '\0';
-
-      while (*fptr && !_cups_isspace(*fptr) && *fptr != ',')
-        fptr ++;
-    }
-
-    DEBUG_printf(("4httpGetSubField2: value=\"%s\"", value));
-
-   /*
-    * See if this is the one...
-    */
-
-    if (!strcmp(name, temp))
-    {
-      DEBUG_printf(("3httpGetSubField2: Returning \"%s\"", value));
-      return (value);
-    }
-  }
-
-  value[0] = '\0';
-
-  DEBUG_puts("3httpGetSubField2: Returning NULL");
-
-  return (NULL);
-}
-
-
 /*
  * 'httpGets()' - Get a line of text from a HTTP connection.
  */
@@ -1457,6 +1296,189 @@ httpGets(char   *line,                  /* I - Line to read into */
 }
 
 
+/*
+ * 'httpGetState()' - Get the current state of the HTTP request.
+ */
+
+http_state_t                           /* O - HTTP state */
+httpGetState(http_t *http)             /* I - Connection to server */
+{
+  return (http ? http->state : HTTP_ERROR);
+}
+
+
+/*
+ * 'httpGetStatus()' - Get the status of the last HTTP request.
+ *
+ * @since CUPS 1.2/Mac OS X 10.5@
+ */
+
+http_status_t                          /* O - HTTP status */
+httpGetStatus(http_t *http)            /* I - Connection to server */
+{
+  return (http ? http->status : HTTP_ERROR);
+}
+
+
+/*
+ * 'httpGetSubField()' - Get a sub-field value.
+ *
+ * @deprecated@
+ */
+
+char *                                 /* O - Value or NULL */
+httpGetSubField(http_t       *http,    /* I - Connection to server */
+                http_field_t field,    /* I - Field index */
+                const char   *name,    /* I - Name of sub-field */
+               char         *value)    /* O - Value string */
+{
+  return (httpGetSubField2(http, field, name, value, HTTP_MAX_VALUE));
+}
+
+
+/*
+ * 'httpGetSubField2()' - Get a sub-field value.
+ *
+ * @since CUPS 1.2/Mac OS X 10.5@
+ */
+
+char *                                 /* O - Value or NULL */
+httpGetSubField2(http_t       *http,   /* I - Connection to server */
+                 http_field_t field,   /* I - Field index */
+                 const char   *name,   /* I - Name of sub-field */
+                char         *value,   /* O - Value string */
+                int          valuelen) /* I - Size of value buffer */
+{
+  const char   *fptr;                  /* Pointer into field */
+  char         temp[HTTP_MAX_VALUE],   /* Temporary buffer for name */
+               *ptr,                   /* Pointer into string buffer */
+               *end;                   /* End of value buffer */
+
+  DEBUG_printf(("2httpGetSubField2(http=%p, field=%d, name=\"%s\", value=%p, "
+                "valuelen=%d)", http, field, name, value, valuelen));
+
+  if (!http || !name || !value || valuelen < 2 ||
+      field <= HTTP_FIELD_UNKNOWN || field >= HTTP_FIELD_MAX)
+    return (NULL);
+
+  end = value + valuelen - 1;
+
+  for (fptr = http->fields[field]; *fptr;)
+  {
+   /*
+    * Skip leading whitespace...
+    */
+
+    while (_cups_isspace(*fptr))
+      fptr ++;
+
+    if (*fptr == ',')
+    {
+      fptr ++;
+      continue;
+    }
+
+   /*
+    * Get the sub-field name...
+    */
+
+    for (ptr = temp;
+         *fptr && *fptr != '=' && !_cups_isspace(*fptr) &&
+            ptr < (temp + sizeof(temp) - 1);
+         *ptr++ = *fptr++);
+
+    *ptr = '\0';
+
+    DEBUG_printf(("4httpGetSubField2: name=\"%s\"", temp));
+
+   /*
+    * Skip trailing chars up to the '='...
+    */
+
+    while (_cups_isspace(*fptr))
+      fptr ++;
+
+    if (!*fptr)
+      break;
+
+    if (*fptr != '=')
+      continue;
+
+   /*
+    * Skip = and leading whitespace...
+    */
+
+    fptr ++;
+
+    while (_cups_isspace(*fptr))
+      fptr ++;
+
+    if (*fptr == '\"')
+    {
+     /*
+      * Read quoted string...
+      */
+
+      for (ptr = value, fptr ++;
+           *fptr && *fptr != '\"' && ptr < end;
+          *ptr++ = *fptr++);
+
+      *ptr = '\0';
+
+      while (*fptr && *fptr != '\"')
+        fptr ++;
+
+      if (*fptr)
+        fptr ++;
+    }
+    else
+    {
+     /*
+      * Read unquoted string...
+      */
+
+      for (ptr = value;
+           *fptr && !_cups_isspace(*fptr) && *fptr != ',' && ptr < end;
+          *ptr++ = *fptr++);
+
+      *ptr = '\0';
+
+      while (*fptr && !_cups_isspace(*fptr) && *fptr != ',')
+        fptr ++;
+    }
+
+    DEBUG_printf(("4httpGetSubField2: value=\"%s\"", value));
+
+   /*
+    * See if this is the one...
+    */
+
+    if (!strcmp(name, temp))
+    {
+      DEBUG_printf(("3httpGetSubField2: Returning \"%s\"", value));
+      return (value);
+    }
+  }
+
+  value[0] = '\0';
+
+  DEBUG_puts("3httpGetSubField2: Returning NULL");
+
+  return (NULL);
+}
+
+
+/*
+ * 'httpGetVersion()' - Get the HTTP version at the other end.
+ */
+
+http_version_t                         /* O - Version number */
+httpGetVersion(http_t *http)           /* I - Connection to server */
+{
+  return (http ? http->version : HTTP_1_0);
+}
+
+
 /*
  * 'httpHead()' - Send a HEAD request to the server.
  */
@@ -3199,10 +3221,13 @@ _httpWriteGNUTLS(
 
   DEBUG_printf(("6_httpWriteGNUTLS(ptr=%p, data=%p, length=%d)", ptr, data,
                 (int)length));
+#ifdef DEBUG
   http_debug_hex("_httpWriteGNUTLS", data, (int)length);
+#endif /* DEBUG */
 
   bytes = send(((http_t *)ptr)->fd, data, length, 0);
   DEBUG_printf(("_httpWriteGNUTLS: bytes=%d", (int)bytes));
+
   return (bytes);
 }
 #endif /* HAVE_SSL && HAVE_GNUTLS */
index 5e3a42d3a94cb58121f1a9f08e1405a9ea775fd2..a70e85cf524511b9de562ab01adfa45ea60e24bb 100644 (file)
@@ -459,7 +459,12 @@ extern void                httpFreeCredentials(cups_array_t *certs) _CUPS_API_1_5;
 extern int             httpSetCredentials(http_t *http, cups_array_t *certs)
                                           _CUPS_API_1_5;
 extern void            httpSetTimeout(http_t *http, double timeout,
-                                      http_timeout_cb_t cb, void *user_data);
+                                      http_timeout_cb_t cb, void *user_data)
+                                      _CUPS_API_1_5;
+
+/**** New in CUPS 1.6 ****/
+extern http_state_t    httpGetState(http_t *http) _CUPS_API_1_6;
+extern http_version_t  httpGetVersion(http_t *http) _CUPS_API_1_6;
 
 
 /*
index 2120c086519d263169ad8290a98ecddecb4c1813..1fcea0f4ec900e07d04fd4f87f79ca8b37b44d6f 100644 (file)
@@ -3,7 +3,7 @@
  *
  *   Private IPP definitions for CUPS.
  *
- *   Copyright 2007-2010 by Apple Inc.
+ *   Copyright 2007-2011 by Apple Inc.
  *   Copyright 1997-2006 by Easy Software Products.
  *
  *   These coded instructions, statements, and computer programs are the
@@ -46,6 +46,103 @@ extern "C" {
  * Structures...
  */
 
+typedef union _ipp_request_u           /**** Request Header ****/
+{
+  struct                               /* Any Header */
+  {
+    ipp_uchar_t        version[2];             /* Protocol version number */
+    int                op_status;              /* Operation ID or status code*/
+    int                request_id;             /* Request ID */
+  }            any;
+
+  struct                               /* Operation Header */
+  {
+    ipp_uchar_t        version[2];             /* Protocol version number */
+    ipp_op_t   operation_id;           /* Operation ID */
+    int                request_id;             /* Request ID */
+  }            op;
+
+  struct                               /* Status Header */
+  {
+    ipp_uchar_t        version[2];             /* Protocol version number */
+    ipp_status_t status_code;          /* Status code */
+    int                request_id;             /* Request ID */
+  }            status;
+
+  /**** New in CUPS 1.1.19 ****/
+  struct                               /* Event Header @since CUPS 1.1.19/Mac OS X 10.3@ */
+  {
+    ipp_uchar_t        version[2];             /* Protocol version number */
+    ipp_status_t status_code;          /* Status code */
+    int                request_id;             /* Request ID */
+  }            event;
+} _ipp_request_t;
+
+/**** New in CUPS 1.1.19 ****/
+
+typedef union _ipp_value_u             /**** Attribute Value ****/
+{
+  int          integer;                /* Integer/enumerated value */
+
+  char         boolean;                /* Boolean value */
+
+  ipp_uchar_t  date[11];               /* Date/time value */
+
+  struct
+  {
+    int                xres,                   /* Horizontal resolution */
+               yres;                   /* Vertical resolution */
+    ipp_res_t  units;                  /* Resolution units */
+  }            resolution;             /* Resolution value */
+
+  struct
+  {
+    int                lower,                  /* Lower value */
+               upper;                  /* Upper value */
+  }            range;                  /* Range of integers value */
+
+  struct
+  {
+    char       *language;              /* Language code */
+    char       *text;                  /* String */
+  }            string;                 /* String with language value */
+
+  struct
+  {
+    int                length;                 /* Length of attribute */
+    void       *data;                  /* Data in attribute */
+  }            unknown;                /* Unknown attribute type */
+
+/**** New in CUPS 1.1.19 ****/
+  ipp_t                *collection;            /* Collection value @since CUPS 1.1.19/Mac OS X 10.3@ */
+} _ipp_value_t;
+
+struct _ipp_attribute_s                /**** Attribute ****/
+{
+  ipp_attribute_t *next;               /* Next attribute in list */
+  ipp_tag_t    group_tag,              /* Job/Printer/Operation group tag */
+               value_tag;              /* What type of value is it? */
+  char         *name;                  /* Name of attribute */
+  int          num_values;             /* Number of values */
+  _ipp_value_t values[1];              /* Values */
+};
+
+struct _ipp_s                          /**** IPP Request/Response/Notification ****/
+{
+  ipp_state_t          state;          /* State of request */
+  _ipp_request_t       request;        /* Request header */
+  ipp_attribute_t      *attrs;         /* Attributes */
+  ipp_attribute_t      *last;          /* Last attribute in list */
+  ipp_attribute_t      *current;       /* Current attribute (for read/write) */
+  ipp_tag_t            curtag;         /* Current attribute group tag */
+
+/**** New in CUPS 1.2 ****/
+  ipp_attribute_t      *prev;          /* Previous attribute (for read) @since CUPS 1.2/Mac OS X 10.5@ */
+
+/**** New in CUPS 1.4.4 ****/
+  int                  use;            /* Use count @since CUPS 1.4.4/Mac OS X 10.6.?@ */
+};
+
 typedef struct _ipp_buffer_s           /**** Read/write buffer ****/
 {
   unsigned char                d[IPP_BUF_SIZE];/* Data buffer */
@@ -66,11 +163,7 @@ typedef struct                              /**** Attribute mapping data ****/
  * Prototypes for private functions...
  */
 
-extern ipp_attribute_t *_ippAddAttr(ipp_t *ipp, int num_values);
-extern size_t          _ippAttrString(ipp_attribute_t *attr, char *buffer,
-                                      size_t bufsize);
 extern _ipp_option_t   *_ippFindOption(const char *name);
-extern void            _ippFreeAttr(ipp_attribute_t *attr);
 
 
 /*
index b22b4727be7b53ca59b66a2ee5d4c26669f54bb3..030eece1e4e86fe1c141d7c5885442c878d977ff 100644 (file)
  *
  * Contents:
  *
- *   _ippAttrString() - Convert the attribute's value to a string.
- *   ippErrorString() - Return a name for the given status code.
- *   ippErrorValue()  - Return a status code for the given name.
- *   ippOpString()    - Return a name for the given operation id.
- *   ippOpValue()     - Return an operation id for the given name.
- *   ippPort()        - Return the default IPP port number.
- *   ippSetPort()     - Set the default port number.
- *   ippTagString()   - Return the tag name corresponding to a tag value.
- *   ippTagValue()    - Return the tag value corresponding to a tag name.
- *   ipp_col_string() - Convert a collection to a string.
+ *   ippAttributeString() - Convert the attribute's value to a string.
+ *   ippEnumString()     - Return a string corresponding to the enum value.
+ *   ippEnumValue()      - Return the value associated with a given enum
+ *                         string.
+ *   ippErrorString()    - Return a name for the given status code.
+ *   ippErrorValue()     - Return a status code for the given name.
+ *   ippOpString()       - Return a name for the given operation id.
+ *   ippOpValue()        - Return an operation id for the given name.
+ *   ippPort()           - Return the default IPP port number.
+ *   ippSetPort()        - Set the default port number.
+ *   ippTagString()      - Return the tag name corresponding to a tag value.
+ *   ippTagValue()       - Return the tag value corresponding to a tag name.
+ *   ipp_col_string()    - Convert a collection to a string.
  */
 
 /*
  */
 
 static const char * const ipp_status_oks[] =   /* "OK" status codes */
-               {
+               {                               /* (name) = abandoned standard value */
                  "successful-ok",
                  "successful-ok-ignored-or-substituted-attributes",
                  "successful-ok-conflicting-attributes",
                  "successful-ok-ignored-subscriptions",
-                 "successful-ok-ignored-notifications",
+                 "(successful-ok-ignored-notifications)",
                  "successful-ok-too-many-events",
-                 "successful-ok-but-cancel-subscription",
+                 "(successful-ok-but-cancel-subscription)",
                  "successful-ok-events-complete"
                },
                * const ipp_status_400s[] =     /* Client errors */
-               {
+               {                               /* (name) = abandoned standard value */
                  "client-error-bad-request",
                  "client-error-forbidden",
                  "client-error-not-authenticated",
@@ -74,8 +77,8 @@ static const char * const ipp_status_oks[] =  /* "OK" status codes */
                  "client-error-attributes-not-settable",
                  "client-error-ignored-all-subscriptions",
                  "client-error-too-many-subscriptions",
-                 "client-error-ignored-all-notifications",
-                 "client-error-print-support-file-not-found"
+                 "(client-error-ignored-all-notifications)",
+                 "(client-error-client-print-support-file-not-found)"
                },
                * const ipp_status_500s[] =             /* Server errors */
                {
@@ -89,7 +92,9 @@ static const char * const ipp_status_oks[] =  /* "OK" status codes */
                  "server-error-busy",
                  "server-error-job-canceled",
                  "server-error-multiple-document-jobs-not-supported",
-                 "server-error-printer-is-deactivated"
+                 "server-error-printer-is-deactivated",
+                 "server-error-too-many-jobs",
+                 "server-error-too-many-documents"
                },
                * const ipp_status_1000s[] =            /* CUPS internal */
                {
@@ -97,7 +102,7 @@ static const char * const ipp_status_oks[] = /* "OK" status codes */
                  "cups-pki-error",
                  "cups-upgrade-required"
                };
-static char    * const ipp_std_ops[] =
+static const char * const ipp_std_ops[] =
                {
                  /* 0x0000 - 0x000f */
                  "0x00",
@@ -131,13 +136,13 @@ static char       * const ipp_std_ops[] =
                  "Renew-Subscription",
                  "Cancel-Subscription",
                  "Get-Notifications",
-                 "Send-Notifications",
-                 "0x1e",
-                 "0x1f",
+                 "(Send-Notifications)",
+                 "(Get-Resource-Attributes)",
+                 "(Get-Resource-Data)",
 
                  /* 0x0020 - 0x002f */
-                 "0x20",
-                 "Get-Printer-Support-Files",
+                 "(Get-Resources)",
+                 "(Get-Printer-Support-Files)",
                  "Enable-Printer",
                  "Disable-Printer",
                  "Pause-Printer-After-Current-Job",
@@ -206,7 +211,8 @@ static char * const ipp_std_ops[] =
                                        /* 0x06 */
                  "event-notification-attributes-tag",
                                        /* 0x07 */
-                 "0x08",               /* 0x08 */
+                 "(resource-attributes-tag)",
+                                       /* 0x08 */
                  "document-attributes-tag",
                                        /* 0x09 */
                  "0x0a",               /* 0x0a */
@@ -275,22 +281,115 @@ static char      * const ipp_std_ops[] =
                  "mimeMediaType",      /* 0x49 */
                  "memberAttrName"      /* 0x4a */
                };
-static const char * const job_states[] =
-{                                      /* job-state enums */
-  "pending",
-  "pending-held",
-  "processing",
-  "processing-stopped",
-  "canceled",
-  "aborted",
-  "completed"
-};
-static const char * const printer_states[] =
-{                                      /* printer-state enums */
-  "idle",
-  "processing",
-  "stopped",
-};
+static const char * const ipp_document_states[] =
+               {                       /* document-state-enums */
+                 "pending",
+                 "4",
+                 "processing",
+                 "6",
+                 "canceled",
+                 "aborted",
+                 "completed"
+               },
+               * const ipp_finishings[] =
+               {                       /* finishings enums */
+                 "none",
+                 "staple",
+                 "punch",
+                 "cover",
+                 "bind",
+                 "saddle-stitch",
+                 "edge-stitch",
+                 "fold",
+                 "trim",
+                 "bale",
+                 "booklet-maker",
+                 "jog-offset",
+                 "15",
+                 "16",
+                 "17",
+                 "18",
+                 "19",
+                 "staple-top-left",
+                 "staple-bottom-left",
+                 "staple-top-right",
+                 "staple-bottom-right",
+                 "edge-stitch-left",
+                 "edge-stitch-top",
+                 "edge-stitch-right",
+                 "edge-stitch-bottom",
+                 "staple-dual-left",
+                 "staple-dual-top",
+                 "staple-dual-right",
+                 "staple-dual-bottom",
+                 "32",
+                 "33",
+                 "34",
+                 "35",
+                 "36",
+                 "37",
+                 "38",
+                 "39",
+                 "40",
+                 "41",
+                 "42",
+                 "43",
+                 "44",
+                 "45",
+                 "46",
+                 "47",
+                 "48",
+                 "49",
+                 "bind-left",
+                 "bind-top",
+                 "bind-right",
+                 "bind-bottom",
+                 "54",
+                 "55",
+                 "56",
+                 "57",
+                 "58",
+                 "59",
+                 "trim-after-pages",
+                 "trim-after-documents",
+                 "trim-after-copies",
+                 "trim-after-job"
+               },
+               * const ipp_job_collation_types[] =
+               {                       /* job-collation-type enums */
+                 "uncollated-sheets",
+                 "collated-documents",
+                 "uncollated-documents"
+               },
+               * const ipp_job_states[] =
+               {                       /* job-state enums */
+                 "pending",
+                 "pending-held",
+                 "processing",
+                 "processing-stopped",
+                 "canceled",
+                 "aborted",
+                 "completed"
+               },
+               * const ipp_orientation_requesteds[] =
+               {                       /* orientation-requested enums */
+                 "portrait",
+                 "landscape",
+                 "reverse-landscape",
+                 "reverse-portrait"
+               },
+               * const ipp_print_qualities[] =
+               {                       /* print-quality enums */
+                 "draft",
+                 "normal",
+                 "high"
+               },
+               * const ipp_printer_states[] =
+               {                       /* printer-state enums */
+                 "idle",
+                 "processing",
+                 "stopped",
+               };
 
 
 /*
@@ -301,24 +400,27 @@ static size_t     ipp_col_string(ipp_t *col, char *buffer, size_t bufsize);
 
 
 /*
- * '_ippAttrString()' - Convert the attribute's value to a string.
+ * 'ippAttributeString()' - Convert the attribute's value to a string.
  *
  * Returns the number of bytes that would be written, not including the
  * trailing nul. The buffer pointer can be NULL to get the required length,
  * just like (v)snprintf.
+ *
+ * @since CUPS 1.6@
  */
 
 size_t                                 /* O - Number of bytes less nul */
-_ippAttrString(ipp_attribute_t *attr,  /* I - Attribute */
-               char            *buffer,        /* I - String buffer or NULL */
-               size_t          bufsize)        /* I - Size of string buffer */
+ippAttributeString(
+    ipp_attribute_t *attr,             /* I - Attribute */
+    char            *buffer,           /* I - String buffer or NULL */
+    size_t          bufsize)           /* I - Size of string buffer */
 {
   int          i;                      /* Looping var */
   char         *bufptr,                /* Pointer into buffer */
                *bufend,                /* End of buffer */
                temp[256];              /* Temporary string */
   const char   *ptr;                   /* Pointer into string */
-  ipp_value_t  *val;                   /* Current value */
+  _ipp_value_t *val;                   /* Current value */
 
 
   if (!attr || !attr->name)
@@ -348,40 +450,13 @@ _ippAttrString(ipp_attribute_t *attr,     /* I - Attribute */
     switch (attr->value_tag & ~IPP_TAG_COPY)
     {
       case IPP_TAG_ENUM :
-          if (!strcmp(attr->name, "printer-state") &&
-              val->integer >= IPP_PRINTER_IDLE &&
-              val->integer <= IPP_PRINTER_STOPPED)
-          {
-            ptr = printer_states[val->integer - IPP_PRINTER_IDLE];
+          ptr = ippEnumString(attr->name, val->integer);
 
-            if (buffer && bufptr < bufend)
-              strlcpy(bufptr, ptr, bufend - bufptr + 1);
-
-            bufptr += strlen(ptr);
-            break;
-          }
-          else if (!strcmp(attr->name, "job-state") &&
-                  val->integer >= IPP_JOB_PENDING &&
-                  val->integer <= IPP_JOB_COMPLETED)
-          {
-            ptr = job_states[val->integer - IPP_JOB_PENDING];
-
-            if (buffer && bufptr < bufend)
-              strlcpy(bufptr, ptr, bufend - bufptr + 1);
-
-            bufptr += strlen(ptr);
-            break;
-          }
-          else if (!strcmp(attr->name, "operations-supported"))
-          {
-            ptr = ippOpString(val->integer);
-
-            if (buffer && bufptr < bufend)
-              strlcpy(bufptr, ptr, bufend - bufptr + 1);
+          if (buffer && bufptr < bufend)
+            strlcpy(bufptr, ptr, bufend - bufptr + 1);
 
-            bufptr += strlen(ptr);
-            break;
-          }
+          bufptr += strlen(ptr);
+          break;
 
       case IPP_TAG_INTEGER :
           if (buffer && bufptr < bufend)
@@ -459,7 +534,7 @@ _ippAttrString(ipp_attribute_t *attr,       /* I - Attribute */
 
           for (ptr = val->string.text; *ptr; ptr ++)
           {
-            if (*ptr == '\\' || *ptr == '\"')
+            if (*ptr == '\\' || *ptr == '\"' || *ptr == '[')
             {
               if (buffer && bufptr < bufend)
                 *bufptr = '\\';
@@ -470,6 +545,25 @@ _ippAttrString(ipp_attribute_t *attr,      /* I - Attribute */
               *bufptr = *ptr;
             bufptr ++;
           }
+
+          if (val->string.language)
+          {
+           /*
+            * Add "[language]" to end of string...
+            */
+
+            if (buffer && bufptr < bufend)
+              *bufptr = '[';
+            bufptr ++;
+
+            if (buffer && bufptr < bufend)
+              strlcpy(bufptr, val->string.language, bufend - bufptr);
+            bufptr += strlen(val->string.language);
+
+            if (buffer && bufptr < bufend)
+              *bufptr = ']';
+            bufptr ++;
+          }
           break;
 
       case IPP_TAG_BEGIN_COLLECTION :
@@ -529,6 +623,159 @@ _ippAttrString(ipp_attribute_t *attr,     /* I - Attribute */
 }
 
 
+/*
+ * 'ippEnumString()' - Return a string corresponding to the enum value.
+ */
+
+const char *                           /* O - Enum string */
+ippEnumString(const char *attrname,    /* I - Attribute name */
+              int        enumvalue)    /* I - Enum value */
+{
+  _cups_globals_t *cg = _cupsGlobals();        /* Pointer to library globals */
+
+
+ /*
+  * Check for standard enum values...
+  */
+
+  if (!strcmp(attrname, "document-state") &&
+      enumvalue >= 3 &&
+      enumvalue <= (3 + (int)(sizeof(ipp_document_states) /
+                              sizeof(ipp_document_states[0]))))
+    return (ipp_document_states[enumvalue - 3]);
+  else if ((!strcmp(attrname, "finishings") ||
+            !strcmp(attrname, "finishings-actual") ||
+            !strcmp(attrname, "finishings-default") ||
+            !strcmp(attrname, "finishings-ready") ||
+            !strcmp(attrname, "finishings-supported")) &&
+           enumvalue >= 3 &&
+           enumvalue <= (3 + (int)(sizeof(ipp_finishings) / sizeof(ipp_finishings[0]))))
+    return (ipp_finishings[enumvalue - 3]);
+  else if ((!strcmp(attrname, "job-collation-type") ||
+            !strcmp(attrname, "job-collation-type-actual")) &&
+           enumvalue >= 3 &&
+           enumvalue <= (3 + (int)(sizeof(ipp_job_collation_types) /
+                                   sizeof(ipp_job_collation_types[0]))))
+    return (ipp_job_collation_types[enumvalue - 3]);
+  else if (!strcmp(attrname, "job-state") &&
+          enumvalue >= IPP_JOB_PENDING && enumvalue <= IPP_JOB_COMPLETED)
+    return (ipp_job_states[enumvalue - IPP_JOB_PENDING]);
+  else if (!strcmp(attrname, "operations-supported"))
+    return (ippOpString((ipp_op_t)enumvalue));
+  else if ((!strcmp(attrname, "orientation-requested") ||
+            !strcmp(attrname, "orientation-requested-actual") ||
+            !strcmp(attrname, "orientation-requested-default") ||
+            !strcmp(attrname, "orientation-requested-supported")) &&
+           enumvalue >= 3 &&
+           enumvalue <= (3 + (int)(sizeof(ipp_orientation_requesteds) /
+                                   sizeof(ipp_orientation_requesteds[0]))))
+    return (ipp_orientation_requesteds[enumvalue - 3]);
+  else if ((!strcmp(attrname, "print-quality") ||
+            !strcmp(attrname, "print-quality-actual") ||
+            !strcmp(attrname, "print-quality-default") ||
+            !strcmp(attrname, "print-quality-supported")) &&
+           enumvalue >= 3 &&
+           enumvalue <= (3 + (int)(sizeof(ipp_print_qualities) /
+                                   sizeof(ipp_print_qualities[0]))))
+    return (ipp_print_qualities[enumvalue - 3]);
+  else if (!strcmp(attrname, "printer-state") &&
+           enumvalue >= IPP_PRINTER_IDLE && enumvalue <= IPP_PRINTER_STOPPED)
+    return (ipp_printer_states[enumvalue - IPP_PRINTER_IDLE]);
+
+ /*
+  * Not a standard enum value, just return the decimal equivalent...
+  */
+
+  snprintf(cg->ipp_unknown, sizeof(cg->ipp_unknown), "%d", enumvalue);
+  return (cg->ipp_unknown);
+}
+
+
+/*
+ * 'ippEnumValue()' - Return the value associated with a given enum string.
+ */
+
+int                                    /* O - Enum value or -1 if unknown */
+ippEnumValue(const char *attrname,     /* I - Attribute name */
+             const char *enumstring)   /* I - Enum string */
+{
+  int          i,                      /* Looping var */
+               num_strings;            /* Number of strings to compare */
+  const char * const *strings;         /* Strings to compare */
+
+
+ /*
+  * If the string is just a number, return it...
+  */
+
+  if (isdigit(*enumstring & 255))
+    return (strtol(enumstring, NULL, 0));
+
+ /*
+  * Otherwise look up the string...
+  */
+
+  if (!strcmp(attrname, "document-state"))
+  {
+    num_strings = (int)(sizeof(ipp_document_states) / sizeof(ipp_document_states[0]));
+    strings     = ipp_document_states;
+  }
+  else if (!strcmp(attrname, "finishings") ||
+          !strcmp(attrname, "finishings-actual") ||
+          !strcmp(attrname, "finishings-default") ||
+          !strcmp(attrname, "finishings-ready") ||
+          !strcmp(attrname, "finishings-supported"))
+  {
+    num_strings = (int)(sizeof(ipp_finishings) / sizeof(ipp_finishings[0]));
+    strings     = ipp_finishings;
+  }
+  else if (!strcmp(attrname, "job-collation-type") ||
+           !strcmp(attrname, "job-collation-type-actual"))
+  {
+    num_strings = (int)(sizeof(ipp_job_collation_types) /
+                        sizeof(ipp_job_collation_types[0]));
+    strings     = ipp_job_collation_types;
+  }
+  else if (!strcmp(attrname, "job-state"))
+  {
+    num_strings = (int)(sizeof(ipp_job_states) / sizeof(ipp_job_states[0]));
+    strings     = ipp_job_states;
+  }
+  else if (!strcmp(attrname, "operations-supported"))
+    return (ippOpValue(enumstring));
+  else if (!strcmp(attrname, "orientation-requested") ||
+           !strcmp(attrname, "orientation-requested-actual") ||
+           !strcmp(attrname, "orientation-requested-default") ||
+           !strcmp(attrname, "orientation-requested-supported"))
+  {
+    num_strings = (int)(sizeof(ipp_orientation_requesteds) /
+                        sizeof(ipp_orientation_requesteds[0]));
+    strings     = ipp_orientation_requesteds;
+  }
+  else if (!strcmp(attrname, "print-quality") ||
+           !strcmp(attrname, "print-quality-actual") ||
+           !strcmp(attrname, "print-quality-default") ||
+           !strcmp(attrname, "print-quality-supported"))
+  {
+    num_strings = (int)(sizeof(ipp_print_qualities) / sizeof(ipp_print_qualities[0]));
+    strings     = ipp_print_qualities;
+  }
+  else if (!strcmp(attrname, "printer-state"))
+  {
+    num_strings = (int)(sizeof(ipp_printer_states) / sizeof(ipp_printer_states[0]));
+    strings     = ipp_printer_states;
+  }
+  else
+    return (-1);
+
+  for (i = 0; i < num_strings; i ++)
+    if (!strcmp(enumstring, strings[i]))
+      return (i + 3);
+
+  return (-1);
+}
+
+
 /*
  * 'ippErrorString()' - Return a name for the given status code.
  */
@@ -811,9 +1058,9 @@ ipp_col_string(ipp_t  *col,                /* I - Collection attribute */
       bufptr += strlen(attr->name) + 1;
 
     if (buffer && bufptr < bufend)
-      bufptr += _ippAttrString(attr, bufptr, bufend - bufptr + 1);
+      bufptr += ippAttributeString(attr, bufptr, bufend - bufptr + 1);
     else
-      bufptr += _ippAttrString(attr, temp, sizeof(temp));
+      bufptr += ippAttributeString(attr, temp, sizeof(temp));
   }
 
   if (buffer && bufptr < bufend)
index d752c35c02f2cbda41013d3d764c7d0d31a2f890..0e22b49ff8299289996773626de4690ecd871017 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: ipp.c 7847 2008-08-19 04:22:14Z mike $"
+ * "$Id: ipp.c 10102 2011-11-02 23:52:39Z mike $"
  *
  *   Internet Printing Protocol functions for CUPS.
  *
  *
  * Contents:
  *
- *   ippAddBoolean()        - Add a boolean attribute to an IPP message.
- *   ippAddBooleans()       - Add an array of boolean values.
- *   ippAddDate()           - Add a date attribute to an IPP message.
- *   ippAddInteger()        - Add a integer attribute to an IPP message.
- *   ippAddIntegers()       - Add an array of integer values.
+ *   ippAddBoolean()       - Add a boolean attribute to an IPP message.
+ *   ippAddBooleans()      - Add an array of boolean values.
+ *   ippAddCollection()     - Add a collection value.
+ *   ippAddCollections()    - Add an array of collection values.
+ *   ippAddDate()          - Add a date attribute to an IPP message.
+ *   ippAddInteger()       - Add a integer attribute to an IPP message.
+ *   ippAddIntegers()      - Add an array of integer values.
  *   ippAddOctetString()    - Add an octetString value to an IPP message.
- *   ippAddString()         - Add a language-encoded string to an IPP message.
- *   ippAddStrings()        - Add language-encoded strings to an IPP message.
- *   ippAddRange()          - Add a range of values to an IPP message.
- *   ippAddRanges()         - Add ranges of values to an IPP message.
+ *   ippAddOutOfBand()     - Add an out-of-band value to an IPP message.
+ *   ippAddRange()         - Add a range of values to an IPP message.
+ *   ippAddRanges()        - Add ranges of values to an IPP message.
  *   ippAddResolution()     - Add a resolution value to an IPP message.
  *   ippAddResolutions()    - Add resolution values to an IPP message.
- *   ippAddSeparator()      - Add a group separator to an IPP message.
- *   ippDateToTime()        - Convert from RFC 1903 Date/Time format to
- *                            UNIX time in seconds.
- *   ippDelete()            - Delete an IPP message.
+ *   ippAddSeparator()     - Add a group separator to an IPP message.
+ *   ippAddString()        - Add a language-encoded string to an IPP message.
+ *   ippAddStrings()       - Add language-encoded strings to an IPP message.
+ *   ippCopyAttribute()     - Copy an attribute.
+ *   ippCopyAttributes()    - Copy attributes from one IPP message to another.
+ *   ippDateToTime()       - Convert from RFC 1903 Date/Time format to UNIX
+ *                           time in seconds.
+ *   ippDelete()           - Delete an IPP message.
  *   ippDeleteAttribute()   - Delete a single attribute in an IPP message.
+ *   ippDeleteValues()     - Delete values in an attribute.
  *   ippFindAttribute()     - Find a named attribute in a request...
  *   ippFindNextAttribute() - Find the next named attribute in a request...
- *   ippLength()            - Compute the length of an IPP message.
- *   ippNew()               - Allocate a new IPP message.
- *   ippNewRequest()        - Allocate a new IPP message.
- *   ippRead()              - Read data for an IPP message from a HTTP
- *                            connection.
- *   ippReadFile()          - Read data for an IPP message from a file.
- *   ippReadIO()            - Read data for an IPP message.
- *   ippTimeToDate()        - Convert from UNIX time to RFC 1903 format.
- *   ippWrite()             - Write data for an IPP message to a HTTP
- *                            connection.
- *   ippWriteFile()         - Write data for an IPP message to a file.
- *   ippWriteIO()           - Write data for an IPP message.
- *   _ippAddAttr()          - Add a new attribute to the request.
- *   _ippFreeAttr()         - Free an attribute.
- *   ipp_length()           - Compute the length of an IPP message or
- *                            collection value.
- *   ipp_read_http()        - Semi-blocking read on a HTTP connection...
- *   ipp_read_file()        - Read IPP data from a file.
- *   ipp_write_file()       - Write IPP data to a file.
+ *   ippFirstAttribute()    - Return the first attribute in the message.
+ *   ippGetBoolean()       - Get a boolean value for an attribute.
+ *   ippGetCollection()     - Get a collection value for an attribute.
+ *   ippGetCount()         - Get the number of values in an attribute.
+ *   ippGetGroupTag()      - Get the group associated with an attribute.
+ *   ippGetInteger()       - Get the integer/enum value for an attribute.
+ *   ippGetName()          - Get the attribute name.
+ *   ippGetOperation()     - Get the operation ID in an IPP message.
+ *   ippGetRequestId()     - Get the request ID from an IPP message.
+ *   ippGetResolution()     - Get a resolution value for an attribute.
+ *   ippGetStatusCode()     - Get the status code from an IPP response or event
+ *                           message.
+ *   ippGetString()        - Get the string and optionally the language code
+ *                           for an attribute.
+ *   ippGetValueTag()      - Get the value tag for an attribute.
+ *   ippGetVersion()       - Get the major and minor version number from an
+ *                           IPP message.
+ *   ippLength()           - Compute the length of an IPP message.
+ *   ippNextAttribute()     - Return the next attribute in the message.
+ *   ippNew()              - Allocate a new IPP message.
+ *   ippNewRequest()       - Allocate a new IPP request message.
+ *   ippRead()             - Read data for an IPP message from a HTTP
+ *                           connection.
+ *   ippReadFile()         - Read data for an IPP message from a file.
+ *   ippReadIO()           - Read data for an IPP message.
+ *   ippSetBoolean()       - Set a boolean value in an attribute.
+ *   ippSetCollection()     - Set a collection value in an attribute.
+ *   ippSetGroupTag()      - Set the group tag of an attribute.
+ *   ippSetInteger()       - Set an integer or enum value in an attribute.
+ *   ippSetName()          - Set the name of an attribute.
+ *   ippSetOperation()     - Set the operation ID in an IPP request message.
+ *   ippSetRange()         - Set a rangeOfInteger value in an attribute.
+ *   ippSetRequestId()     - Set the request ID in an IPP message.
+ *   ippSetResolution()     - Set a resolution value in an attribute.
+ *   ippSetStatusCode()     - Set the status code in an IPP response or event
+ *                           message.
+ *   ippSetString()        - Set a string value in an attribute.
+ *   ippSetValueTag()      - Set the value tag of an attribute.
+ *   ippSetVersion()       - Set the version number in an IPP message.
+ *   ippTimeToDate()       - Convert from UNIX time to RFC 1903 format.
+ *   ippWrite()            - Write data for an IPP message to a HTTP
+ *                           connection.
+ *   ippWriteFile()        - Write data for an IPP message to a file.
+ *   ippWriteIO()          - Write data for an IPP message.
+ *   ipp_add_attr()        - Add a new attribute to the message.
+ *   ipp_buffer_get()      - Get a read/write buffer.
+ *   ipp_buffer_release()   - Release a read/write buffer.
+ *   ipp_free_values()     - Free attribute values.
+ *   ipp_get_code()        - Convert a C locale/charset name into an IPP
+ *                           language/charset code.
+ *   ipp_lang_code()       - Convert a C locale name into an IPP language
+ *                           code.
+ *   ipp_length()          - Compute the length of an IPP message or
+ *                           collection value.
+ *   ipp_read_http()       - Semi-blocking read on a HTTP connection...
+ *   ipp_read_file()       - Read IPP data from a file.
+ *   ipp_set_value()       - Get the value element from an attribute,
+ *                           expanding it as needed.
+ *   ipp_write_file()      - Write IPP data to a file.
  */
 
 /*
  * Local functions...
  */
 
+static ipp_attribute_t *ipp_add_attr(ipp_t *ipp, const char *name, ipp_tag_t  group_tag,
+                                     ipp_tag_t value_tag, int num_values);
 static unsigned char   *ipp_buffer_get(void);
 static void            ipp_buffer_release(unsigned char *b);
+static void            ipp_free_values(ipp_attribute_t *attr, int element, int count);
+static char            *ipp_get_code(const char *locale, char *buffer, size_t bufsize);
+static char            *ipp_lang_code(const char *locale, char *buffer, size_t bufsize);
 static size_t          ipp_length(ipp_t *ipp, int collection);
 static ssize_t         ipp_read_http(http_t *http, ipp_uchar_t *buffer,
                                      size_t length);
 static ssize_t         ipp_read_file(int *fd, ipp_uchar_t *buffer,
                                      size_t length);
+static _ipp_value_t    *ipp_set_value(ipp_t *ipp, ipp_attribute_t **attr, int element);
 static ssize_t         ipp_write_file(int *fd, ipp_uchar_t *buffer,
                                       size_t length);
 
 
 /*
  * 'ippAddBoolean()' - Add a boolean attribute to an IPP message.
+ *
+ * The @code ipp@ parameter refers to an IPP message previously created using the
+ * @link ippNew@ or @link ippNewRequest@ functions.
+ *
+ * The @code group@ parameter specifies the IPP attribute group tag: none
+ * (@code IPP_TAG_ZERO@, for member attributes), document (@code IPP_TAG_DOCUMENT@),
+ * event notification (@code IPP_TAG_EVENT_NOTIFICATION@), operation
+ * (@code IPP_TAG_OPERATION@), printer (@code IPP_TAG_PRINTER@), subscription
+ * (@code IPP_TAG_SUBSCRIPTION@), or unsupported (@code IPP_TAG_UNSUPPORTED_GROUP@).
  */
 
 ipp_attribute_t *                      /* O - New attribute */
@@ -97,15 +158,21 @@ ippAddBoolean(ipp_t      *ipp,             /* I - IPP message */
   DEBUG_printf(("ippAddBoolean(ipp=%p, group=%02x(%s), name=\"%s\", value=%d)",
                 ipp, group, ippTagString(group), name, value));
 
-  if (!ipp || !name)
+ /*
+  * Range check input...
+  */
+
+  if (!ipp || !name || group < IPP_TAG_ZERO ||
+      group == IPP_TAG_END || group >= IPP_TAG_UNSUPPORTED_VALUE)
     return (NULL);
 
-  if ((attr = _ippAddAttr(ipp, 1)) == NULL)
+ /*
+  * Create the attribute...
+  */
+
+  if ((attr = ipp_add_attr(ipp, name, group, IPP_TAG_BOOLEAN, 1)) == NULL)
     return (NULL);
 
-  attr->name              = _cupsStrAlloc(name);
-  attr->group_tag         = group;
-  attr->value_tag         = IPP_TAG_BOOLEAN;
   attr->values[0].boolean = value;
 
   return (attr);
@@ -114,6 +181,15 @@ ippAddBoolean(ipp_t      *ipp,             /* I - IPP message */
 
 /*
  * 'ippAddBooleans()' - Add an array of boolean values.
+ *
+ * The @code ipp@ parameter refers to an IPP message previously created using the
+ * @link ippNew@ or @link ippNewRequest@ functions.
+ *
+ * The @code group@ parameter specifies the IPP attribute group tag: none
+ * (@code IPP_TAG_ZERO@, for member attributes), document (@code IPP_TAG_DOCUMENT@),
+ * event notification (@code IPP_TAG_EVENT_NOTIFICATION@), operation
+ * (@code IPP_TAG_OPERATION@), printer (@code IPP_TAG_PRINTER@), subscription
+ * (@code IPP_TAG_SUBSCRIPTION@), or unsupported (@code IPP_TAG_UNSUPPORTED_GROUP@).
  */
 
 ipp_attribute_t *                      /* O - New attribute */
@@ -125,28 +201,36 @@ ippAddBooleans(ipp_t      *ipp,           /* I - IPP message */
 {
   int                  i;              /* Looping var */
   ipp_attribute_t      *attr;          /* New attribute */
-  ipp_value_t          *value;         /* Current value */
+  _ipp_value_t         *value;         /* Current value */
 
 
   DEBUG_printf(("ippAddBooleans(ipp=%p, group=%02x(%s), name=\"%s\", "
                 "num_values=%d, values=%p)", ipp, group, ippTagString(group),
                 name, num_values, values));
 
-  if (!ipp || !name || num_values < 1)
-    return (NULL);
+ /*
+  * Range check input...
+  */
 
-  if ((attr = _ippAddAttr(ipp, num_values)) == NULL)
+  if (!ipp || !name || group < IPP_TAG_ZERO ||
+      group == IPP_TAG_END || group >= IPP_TAG_UNSUPPORTED_VALUE ||
+      num_values < 1)
     return (NULL);
 
-  attr->name      = _cupsStrAlloc(name);
-  attr->group_tag = group;
-  attr->value_tag = IPP_TAG_BOOLEAN;
+ /*
+  * Create the attribute...
+  */
+
+  if ((attr = ipp_add_attr(ipp, name, group, IPP_TAG_BOOLEAN, num_values)) == NULL)
+    return (NULL);
 
-  if (values != NULL)
-    for (i = 0, value = attr->values;
-        i < num_values;
-        i ++, value ++)
-      value->boolean = values[i];
+  if (values)
+  {
+    for (i = num_values, value = attr->values;
+        i > 0;
+        i --, value ++)
+      value->boolean = *values++;
+  }
 
   return (attr);
 }
@@ -155,6 +239,15 @@ ippAddBooleans(ipp_t      *ipp,            /* I - IPP message */
 /*
  * 'ippAddCollection()' - Add a collection value.
  *
+ * The @code ipp@ parameter refers to an IPP message previously created using the
+ * @link ippNew@ or @link ippNewRequest@ functions.
+ *
+ * The @code group@ parameter specifies the IPP attribute group tag: none
+ * (@code IPP_TAG_ZERO@, for member attributes), document (@code IPP_TAG_DOCUMENT@),
+ * event notification (@code IPP_TAG_EVENT_NOTIFICATION@), operation
+ * (@code IPP_TAG_OPERATION@), printer (@code IPP_TAG_PRINTER@), subscription
+ * (@code IPP_TAG_SUBSCRIPTION@), or unsupported (@code IPP_TAG_UNSUPPORTED_GROUP@).
+ *
  * @since CUPS 1.1.19/Mac OS X 10.3@
  */
 
@@ -170,15 +263,21 @@ ippAddCollection(ipp_t      *ipp, /* I - IPP message */
   DEBUG_printf(("ippAddCollection(ipp=%p, group=%02x(%s), name=\"%s\", "
                 "value=%p)", ipp, group, ippTagString(group), name, value));
 
-  if (!ipp || !name)
+ /*
+  * Range check input...
+  */
+
+  if (!ipp || !name || group < IPP_TAG_ZERO ||
+      group == IPP_TAG_END || group >= IPP_TAG_UNSUPPORTED_VALUE)
     return (NULL);
 
-  if ((attr = _ippAddAttr(ipp, 1)) == NULL)
+ /*
+  * Create the attribute...
+  */
+
+  if ((attr = ipp_add_attr(ipp, name, group, IPP_TAG_BEGIN_COLLECTION, 1)) == NULL)
     return (NULL);
 
-  attr->name                 = _cupsStrAlloc(name);
-  attr->group_tag            = group;
-  attr->value_tag            = IPP_TAG_BEGIN_COLLECTION;
   attr->values[0].collection = value;
 
   value->use ++;
@@ -190,6 +289,15 @@ ippAddCollection(ipp_t      *ipp,  /* I - IPP message */
 /*
  * 'ippAddCollections()' - Add an array of collection values.
  *
+ * The @code ipp@ parameter refers to an IPP message previously created using the
+ * @link ippNew@ or @link ippNewRequest@ functions.
+ *
+ * The @code group@ parameter specifies the IPP attribute group tag: none
+ * (@code IPP_TAG_ZERO@, for member attributes), document (@code IPP_TAG_DOCUMENT@),
+ * event notification (@code IPP_TAG_EVENT_NOTIFICATION@), operation
+ * (@code IPP_TAG_OPERATION@), printer (@code IPP_TAG_PRINTER@), subscription
+ * (@code IPP_TAG_SUBSCRIPTION@), or unsupported (@code IPP_TAG_UNSUPPORTED_GROUP@).
+ *
  * @since CUPS 1.1.19/Mac OS X 10.3@
  */
 
@@ -203,30 +311,37 @@ ippAddCollections(
 {
   int                  i;              /* Looping var */
   ipp_attribute_t      *attr;          /* New attribute */
-  ipp_value_t          *value;         /* Current value */
+  _ipp_value_t         *value;         /* Current value */
 
 
   DEBUG_printf(("ippAddCollections(ipp=%p, group=%02x(%s), name=\"%s\", "
                 "num_values=%d, values=%p)", ipp, group, ippTagString(group),
                 name, num_values, values));
 
-  if (!ipp || !name || num_values < 1)
-    return (NULL);
+ /*
+  * Range check input...
+  */
 
-  if ((attr = _ippAddAttr(ipp, num_values)) == NULL)
+  if (!ipp || !name || group < IPP_TAG_ZERO ||
+      group == IPP_TAG_END || group >= IPP_TAG_UNSUPPORTED_VALUE ||
+      num_values < 1)
     return (NULL);
 
-  attr->name      = _cupsStrAlloc(name);
-  attr->group_tag = group;
-  attr->value_tag = IPP_TAG_BEGIN_COLLECTION;
+ /*
+  * Create the attribute...
+  */
+
+  if ((attr = ipp_add_attr(ipp, name, group, IPP_TAG_BEGIN_COLLECTION,
+                           num_values)) == NULL)
+    return (NULL);
 
-  if (values != NULL)
+  if (values)
   {
-    for (i = 0, value = attr->values;
-        i < num_values;
-        i ++, value ++)
+    for (i = num_values, value = attr->values;
+        i > 0;
+        i --, value ++)
     {
-      value->collection = (ipp_t *)values[i];
+      value->collection = (ipp_t *)*values++;
       value->collection->use ++;
     }
   }
@@ -237,6 +352,15 @@ ippAddCollections(
 
 /*
  * 'ippAddDate()' - Add a date attribute to an IPP message.
+ *
+ * The @code ipp@ parameter refers to an IPP message previously created using the
+ * @link ippNew@ or @link ippNewRequest@ functions.
+ *
+ * The @code group@ parameter specifies the IPP attribute group tag: none
+ * (@code IPP_TAG_ZERO@, for member attributes), document (@code IPP_TAG_DOCUMENT@),
+ * event notification (@code IPP_TAG_EVENT_NOTIFICATION@), operation
+ * (@code IPP_TAG_OPERATION@), printer (@code IPP_TAG_PRINTER@), subscription
+ * (@code IPP_TAG_SUBSCRIPTION@), or unsupported (@code IPP_TAG_UNSUPPORTED_GROUP@).
  */
 
 ipp_attribute_t *                      /* O - New attribute */
@@ -251,15 +375,21 @@ ippAddDate(ipp_t             *ipp,        /* I - IPP message */
   DEBUG_printf(("ippAddDate(ipp=%p, group=%02x(%s), name=\"%s\", value=%p)",
                 ipp, group, ippTagString(group), name, value));
 
-  if (!ipp || !name || !value)
+ /*
+  * Range check input...
+  */
+
+  if (!ipp || !name || !value || group < IPP_TAG_ZERO ||
+      group == IPP_TAG_END || group >= IPP_TAG_UNSUPPORTED_VALUE)
     return (NULL);
 
-  if ((attr = _ippAddAttr(ipp, 1)) == NULL)
+ /*
+  * Create the attribute...
+  */
+
+  if ((attr = ipp_add_attr(ipp, name, group, IPP_TAG_DATE, 1)) == NULL)
     return (NULL);
 
-  attr->name      = _cupsStrAlloc(name);
-  attr->group_tag = group;
-  attr->value_tag = IPP_TAG_DATE;
   memcpy(attr->values[0].date, value, 11);
 
   return (attr);
@@ -268,12 +398,24 @@ ippAddDate(ipp_t             *ipp,        /* I - IPP message */
 
 /*
  * 'ippAddInteger()' - Add a integer attribute to an IPP message.
+ *
+ * The @code ipp@ parameter refers to an IPP message previously created using the
+ * @link ippNew@ or @link ippNewRequest@ functions.
+ *
+ * The @code group@ parameter specifies the IPP attribute group tag: none
+ * (@code IPP_TAG_ZERO@, for member attributes), document (@code IPP_TAG_DOCUMENT@),
+ * event notification (@code IPP_TAG_EVENT_NOTIFICATION@), operation
+ * (@code IPP_TAG_OPERATION@), printer (@code IPP_TAG_PRINTER@), subscription
+ * (@code IPP_TAG_SUBSCRIPTION@), or unsupported (@code IPP_TAG_UNSUPPORTED_GROUP@).
+ *
+ * Supported values include enum (@code IPP_TAG_ENUM@) and integer
+ * (@code IPP_TAG_INTEGER@).
  */
 
 ipp_attribute_t *                      /* O - New attribute */
 ippAddInteger(ipp_t      *ipp,         /* I - IPP message */
               ipp_tag_t  group,                /* I - IPP group */
-             ipp_tag_t  type,          /* I - Type of attribute */
+             ipp_tag_t  value_tag,     /* I - Type of attribute */
               const char *name,                /* I - Name of attribute */
               int        value)                /* I - Value of attribute */
 {
@@ -282,17 +424,40 @@ ippAddInteger(ipp_t      *ipp,            /* I - IPP message */
 
   DEBUG_printf(("ippAddInteger(ipp=%p, group=%02x(%s), type=%02x(%s), "
                 "name=\"%s\", value=%d)", ipp, group, ippTagString(group),
-               type, ippTagString(type), name, value));
+               value_tag, ippTagString(value_tag), name, value));
 
-  if (!ipp || !name)
+  value_tag &= IPP_TAG_MASK;
+
+ /*
+  * Special-case for legacy usage: map out-of-band attributes to new ippAddOutOfBand
+  * function...
+  */
+
+  if (value_tag >= IPP_TAG_UNSUPPORTED_VALUE && value_tag <= IPP_TAG_ADMINDEFINE)
+    return (ippAddOutOfBand(ipp, group, value_tag, name));
+
+ /*
+  * Range check input...
+  */
+
+#if 0
+  if (!ipp || !name || group < IPP_TAG_ZERO ||
+      group == IPP_TAG_END || group >= IPP_TAG_UNSUPPORTED_VALUE ||
+      (value_tag != IPP_TAG_INTEGER && value_tag != IPP_TAG_ENUM))
+    return (NULL);
+#else
+  if (!ipp || !name || group < IPP_TAG_ZERO ||
+      group == IPP_TAG_END || group >= IPP_TAG_UNSUPPORTED_VALUE)
     return (NULL);
+#endif /* 0 */
 
-  if ((attr = _ippAddAttr(ipp, 1)) == NULL)
+ /*
+  * Create the attribute...
+  */
+
+  if ((attr = ipp_add_attr(ipp, name, group, value_tag, 1)) == NULL)
     return (NULL);
 
-  attr->name              = _cupsStrAlloc(name);
-  attr->group_tag         = group;
-  attr->value_tag         = type;
   attr->values[0].integer = value;
 
   return (attr);
@@ -301,41 +466,71 @@ ippAddInteger(ipp_t      *ipp,            /* I - IPP message */
 
 /*
  * 'ippAddIntegers()' - Add an array of integer values.
+ *
+ * The @code ipp@ parameter refers to an IPP message previously created using the
+ * @link ippNew@ or @link ippNewRequest@ functions.
+ *
+ * The @code group@ parameter specifies the IPP attribute group tag: none
+ * (@code IPP_TAG_ZERO@, for member attributes), document (@code IPP_TAG_DOCUMENT@),
+ * event notification (@code IPP_TAG_EVENT_NOTIFICATION@), operation
+ * (@code IPP_TAG_OPERATION@), printer (@code IPP_TAG_PRINTER@), subscription
+ * (@code IPP_TAG_SUBSCRIPTION@), or unsupported (@code IPP_TAG_UNSUPPORTED_GROUP@).
+ *
+ * Supported values include enum (@code IPP_TAG_ENUM@) and integer
+ * (@code IPP_TAG_INTEGER@).
  */
 
 ipp_attribute_t *                      /* O - New attribute */
 ippAddIntegers(ipp_t      *ipp,                /* I - IPP message */
                ipp_tag_t  group,       /* I - IPP group */
-              ipp_tag_t  type,         /* I - Type of attribute */
+              ipp_tag_t  value_tag,    /* I - Type of attribute */
               const char *name,        /* I - Name of attribute */
               int        num_values,   /* I - Number of values */
               const int  *values)      /* I - Values */
 {
   int                  i;              /* Looping var */
   ipp_attribute_t      *attr;          /* New attribute */
-  ipp_value_t          *value;         /* Current value */
+  _ipp_value_t         *value;         /* Current value */
 
 
   DEBUG_printf(("ippAddIntegers(ipp=%p, group=%02x(%s), type=%02x(%s), "
                 "name=\"%s\", num_values=%d, values=%p)", ipp,
-               group, ippTagString(group), type, ippTagString(type), name,
+               group, ippTagString(group), value_tag, ippTagString(value_tag), name,
                num_values, values));
 
-  if (!ipp || !name || num_values < 1)
-    return (NULL);
+  value_tag &= IPP_TAG_MASK;
+
+ /*
+  * Range check input...
+  */
 
-  if ((attr = _ippAddAttr(ipp, num_values)) == NULL)
+#if 0
+  if (!ipp || !name || group < IPP_TAG_ZERO ||
+      group == IPP_TAG_END || group >= IPP_TAG_UNSUPPORTED_VALUE ||
+      (value_tag != IPP_TAG_INTEGER && value_tag != IPP_TAG_ENUM) ||
+      num_values < 1)
+    return (NULL);
+#else
+  if (!ipp || !name || group < IPP_TAG_ZERO ||
+      group == IPP_TAG_END || group >= IPP_TAG_UNSUPPORTED_VALUE ||
+      num_values < 1)
     return (NULL);
+#endif /* 0 */
 
-  attr->name      = _cupsStrAlloc(name);
-  attr->group_tag = group;
-  attr->value_tag = type;
+ /*
+  * Create the attribute...
+  */
+
+  if ((attr = ipp_add_attr(ipp, name, group, value_tag, num_values)) == NULL)
+    return (NULL);
 
-  if (values != NULL)
-    for (i = 0, value = attr->values;
-        i < num_values;
-        i ++, value ++)
-      value->integer = values[i];
+  if (values)
+  {
+    for (i = num_values, value = attr->values;
+        i > 0;
+        i --, value ++)
+      value->integer = *values++;
+  }
 
   return (attr);
 }
@@ -344,6 +539,15 @@ ippAddIntegers(ipp_t      *ipp,            /* I - IPP message */
 /*
  * 'ippAddOctetString()' - Add an octetString value to an IPP message.
  *
+ * The @code ipp@ parameter refers to an IPP message previously created using the
+ * @link ippNew@ or @link ippNewRequest@ functions.
+ *
+ * The @code group@ parameter specifies the IPP attribute group tag: none
+ * (@code IPP_TAG_ZERO@, for member attributes), document (@code IPP_TAG_DOCUMENT@),
+ * event notification (@code IPP_TAG_EVENT_NOTIFICATION@), operation
+ * (@code IPP_TAG_OPERATION@), printer (@code IPP_TAG_PRINTER@), subscription
+ * (@code IPP_TAG_SUBSCRIPTION@), or unsupported (@code IPP_TAG_UNSUPPORTED_GROUP@).
+ *
  * @since CUPS 1.2/Mac OS X 10.5@
  */
 
@@ -357,19 +561,17 @@ ippAddOctetString(ipp_t      *ipp,        /* I - IPP message */
   ipp_attribute_t      *attr;          /* New attribute */
 
 
-  if (ipp == NULL || name == NULL)
+  if (!ipp || !name || group < IPP_TAG_ZERO ||
+      group == IPP_TAG_END || group >= IPP_TAG_UNSUPPORTED_VALUE)
     return (NULL);
 
-  if ((attr = _ippAddAttr(ipp, 1)) == NULL)
+  if ((attr = ipp_add_attr(ipp, name, group, IPP_TAG_STRING, 1)) == NULL)
     return (NULL);
 
  /*
   * Initialize the attribute data...
   */
 
-  attr->name                     = _cupsStrAlloc(name);
-  attr->group_tag                = group;
-  attr->value_tag                = IPP_TAG_STRING;
   attr->values[0].unknown.length = datalen;
 
   if (data)
@@ -392,164 +594,74 @@ ippAddOctetString(ipp_t      *ipp,       /* I - IPP message */
 
 
 /*
- * 'ippAddString()' - Add a language-encoded string to an IPP message.
+ * 'ippAddOutOfBand()' - Add an out-of-band value to an IPP message.
+ *
+ * The @code ipp@ parameter refers to an IPP message previously created using the
+ * @link ippNew@ or @link ippNewRequest@ functions.
+ *
+ * The @code group@ parameter specifies the IPP attribute group tag: none
+ * (@code IPP_TAG_ZERO@, for member attributes), document (@code IPP_TAG_DOCUMENT@),
+ * event notification (@code IPP_TAG_EVENT_NOTIFICATION@), operation
+ * (@code IPP_TAG_OPERATION@), printer (@code IPP_TAG_PRINTER@), subscription
+ * (@code IPP_TAG_SUBSCRIPTION@), or unsupported (@code IPP_TAG_UNSUPPORTED_GROUP@).
+ *
+ * Supported out-of-band values include unsupported-value
+ * (@code IPP_TAG_UNSUPPORTED_VALUE@), default (@code IPP_TAG_DEFAULT@), unknown
+ * (@code IPP_TAG_UNKNOWN@), no-value (@code IPP_TAG_NOVALUE@), not-settable
+ * (@code IPP_TAG_NOTSETTABLE@), delete-attribute (@code IPP_TAG_DELETEATTR@), and
+ * admin-define (@code IPP_TAG_ADMINDEFINE@).
+ *
+ * @since CUPS 1.6@
  */
 
-ipp_attribute_t *                      /* O - New attribute */
-ippAddString(ipp_t      *ipp,          /* I - IPP message */
-             ipp_tag_t  group,         /* I - IPP group */
-            ipp_tag_t  type,           /* I - Type of attribute */
-             const char *name,         /* I - Name of attribute */
-             const char *charset,      /* I - Character set */
-             const char *value)                /* I - Value */
+ipp_attribute_t        *                       /* O - New attribute */
+ippAddOutOfBand(ipp_t      *ipp,       /* I - IPP message */
+                ipp_tag_t  group,      /* I - IPP group */
+                ipp_tag_t  value_tag,  /* I - Type of attribute */
+               const char *name)       /* I - Name of attribute */
 {
-  ipp_attribute_t      *attr;          /* New attribute */
-  char                 buffer[1024],   /* Language/charset value buffer */
-                       *bufptr;        /* Pointer into buffer */
-
-
-  DEBUG_printf(("ippAddString(ipp=%p, group=%02x(%s), type=%02x(%s), "
-                "name=\"%s\", charset=\"%s\", value=\"%s\")", ipp,
-               group, ippTagString(group), type, ippTagString(type), name,
-               charset, value));
-
-  if (!ipp || !name)
-    return (NULL);
-
-  if ((attr = _ippAddAttr(ipp, 1)) == NULL)
-    return (NULL);
-
- /*
-  * Force value to be English for the POSIX locale...
-  */
-
-  if (type == IPP_TAG_LANGUAGE && !_cups_strcasecmp(value, "C"))
-    value = "en";
+  DEBUG_printf(("ippAddOutOfBand(ipp=%p, group=%02x(%s), value_tag=%02x(%s), "
+                "name=\"%s\")", ipp, group, ippTagString(group), value_tag,
+                ippTagString(value_tag), name));
 
- /*
-  * Convert language and charset values to lowercase and change _ to - as
-  * needed...
-  */
-
-  if ((type == IPP_TAG_LANGUAGE || type == IPP_TAG_CHARSET) && value)
-  {
-    strlcpy(buffer, value, sizeof(buffer));
-    value = buffer;
-
-    for (bufptr = buffer; *bufptr; bufptr ++)
-      if (*bufptr == '_')
-        *bufptr = '-';
-      else
-        *bufptr = tolower(*bufptr & 255);
-  }
+  value_tag &= IPP_TAG_MASK;
 
  /*
-  * Initialize the attribute data...
+  * Range check input...
   */
 
-  attr->name                     = _cupsStrAlloc(name);
-  attr->group_tag                = group;
-  attr->value_tag                = type;
-  attr->values[0].string.charset = ((int)type & IPP_TAG_COPY) ? (char *)charset :
-                                   charset ? _cupsStrAlloc(charset) : NULL;
-  attr->values[0].string.text    = ((int)type & IPP_TAG_COPY) ? (char *)value :
-                                   value ? _cupsStrAlloc(value) : NULL;
-
-  return (attr);
-}
-
-
-/*
- * 'ippAddStrings()' - Add language-encoded strings to an IPP message.
- */
-
-ipp_attribute_t *                      /* O - New attribute */
-ippAddStrings(
-    ipp_t              *ipp,           /* I - IPP message */
-    ipp_tag_t          group,          /* I - IPP group */
-    ipp_tag_t          type,           /* I - Type of attribute */
-    const char         *name,          /* I - Name of attribute */
-    int                num_values,     /* I - Number of values */
-    const char         *charset,       /* I - Character set */
-    const char * const *values)                /* I - Values */
-{
-  int                  i;              /* Looping var */
-  ipp_attribute_t      *attr;          /* New attribute */
-  ipp_value_t          *value;         /* Current value */
-  char                 buffer[1024],   /* Language/charset value buffer */
-                       *bufptr;        /* Pointer into buffer */
-
-
-  DEBUG_printf(("ippAddStrings(ipp=%p, group=%02x(%s), type=%02x(%s), "
-                "name=\"%s\", num_values=%d, charset=\"%s\", values=%p)", ipp,
-               group, ippTagString(group), type, ippTagString(type), name,
-               num_values, charset, values));
-
-  if (!ipp || !name || num_values < 1)
-    return (NULL);
-
-  if ((attr = _ippAddAttr(ipp, num_values)) == NULL)
+  if (!ipp || !name || group < IPP_TAG_ZERO ||
+      group == IPP_TAG_END || group >= IPP_TAG_UNSUPPORTED_VALUE ||
+      (value_tag != IPP_TAG_UNSUPPORTED_VALUE &&
+       value_tag != IPP_TAG_DEFAULT &&
+       value_tag != IPP_TAG_UNKNOWN &&
+       value_tag != IPP_TAG_NOVALUE &&
+       value_tag != IPP_TAG_NOTSETTABLE &&
+       value_tag != IPP_TAG_DELETEATTR &&
+       value_tag != IPP_TAG_ADMINDEFINE))
     return (NULL);
 
  /*
-  * Initialize the attribute data...
+  * Create the attribute...
   */
 
-  attr->name      = _cupsStrAlloc(name);
-  attr->group_tag = group;
-  attr->value_tag = type;
-
-  for (i = 0, value = attr->values;
-       i < num_values;
-       i ++, value ++)
-  {
-    if (i == 0)
-      value->string.charset = ((int)type & IPP_TAG_COPY) ? (char *)charset :
-                                   charset ? _cupsStrAlloc(charset) : NULL;
-    else
-      value->string.charset = attr->values[0].string.charset;
-
-    if (values != NULL)
-    {
-      if ((int)type & IPP_TAG_COPY)
-        value->string.text = (char *)values[i];
-      else if (type == IPP_TAG_LANGUAGE && !_cups_strcasecmp(values[i], "C"))
-      {
-       /*
-       * Force language to be English for the POSIX locale...
-       */
-
-       value->string.text = ((int)type & IPP_TAG_COPY) ? "en" :
-                                      _cupsStrAlloc("en");
-      }
-      else if (type == IPP_TAG_LANGUAGE || type == IPP_TAG_CHARSET)
-      {
-       /*
-       * Convert language values to lowercase and change _ to - as needed...
-       */
-
-       strlcpy(buffer, values[i], sizeof(buffer));
-
-       for (bufptr = buffer; *bufptr; bufptr ++)
-         if (*bufptr == '_')
-           *bufptr = '-';
-         else
-           *bufptr = tolower(*bufptr & 255);
-
-       value->string.text = _cupsStrAlloc(buffer);
-      }
-      else
-       value->string.text = _cupsStrAlloc(values[i]);
-
-    }
-  }
-
-  return (attr);
+  return (ipp_add_attr(ipp, name, group, value_tag, 1));
 }
 
 
 /*
  * 'ippAddRange()' - Add a range of values to an IPP message.
+ *
+ * The @code ipp@ parameter refers to an IPP message previously created using the
+ * @link ippNew@ or @link ippNewRequest@ functions.
+ *
+ * The @code group@ parameter specifies the IPP attribute group tag: none
+ * (@code IPP_TAG_ZERO@, for member attributes), document (@code IPP_TAG_DOCUMENT@),
+ * event notification (@code IPP_TAG_EVENT_NOTIFICATION@), operation
+ * (@code IPP_TAG_OPERATION@), printer (@code IPP_TAG_PRINTER@), subscription
+ * (@code IPP_TAG_SUBSCRIPTION@), or unsupported (@code IPP_TAG_UNSUPPORTED_GROUP@).
+ *
+ * The @code lower@ parameter must be less than or equal to the @code upper@ parameter.
  */
 
 ipp_attribute_t *                      /* O - New attribute */
@@ -566,15 +678,21 @@ ippAddRange(ipp_t      *ipp,              /* I - IPP message */
                 "upper=%d)", ipp, group, ippTagString(group), name, lower,
                upper));
 
-  if (!ipp || !name)
+ /*
+  * Range check input...
+  */
+
+  if (!ipp || !name || group < IPP_TAG_ZERO ||
+      group == IPP_TAG_END || group >= IPP_TAG_UNSUPPORTED_VALUE)
     return (NULL);
 
-  if ((attr = _ippAddAttr(ipp, 1)) == NULL)
+ /*
+  * Create the attribute...
+  */
+
+  if ((attr = ipp_add_attr(ipp, name, group, IPP_TAG_RANGE, 1)) == NULL)
     return (NULL);
 
-  attr->name                  = _cupsStrAlloc(name);
-  attr->group_tag             = group;
-  attr->value_tag             = IPP_TAG_RANGE;
   attr->values[0].range.lower = lower;
   attr->values[0].range.upper = upper;
 
@@ -584,6 +702,15 @@ ippAddRange(ipp_t      *ipp,               /* I - IPP message */
 
 /*
  * 'ippAddRanges()' - Add ranges of values to an IPP message.
+ *
+ * The @code ipp@ parameter refers to an IPP message previously created using the
+ * @link ippNew@ or @link ippNewRequest@ functions.
+ *
+ * The @code group@ parameter specifies the IPP attribute group tag: none
+ * (@code IPP_TAG_ZERO@, for member attributes), document (@code IPP_TAG_DOCUMENT@),
+ * event notification (@code IPP_TAG_EVENT_NOTIFICATION@), operation
+ * (@code IPP_TAG_OPERATION@), printer (@code IPP_TAG_PRINTER@), subscription
+ * (@code IPP_TAG_SUBSCRIPTION@), or unsupported (@code IPP_TAG_UNSUPPORTED_GROUP@).
  */
 
 ipp_attribute_t *                      /* O - New attribute */
@@ -596,31 +723,39 @@ ippAddRanges(ipp_t      *ipp,             /* I - IPP message */
 {
   int                  i;              /* Looping var */
   ipp_attribute_t      *attr;          /* New attribute */
-  ipp_value_t          *value;         /* Current value */
+  _ipp_value_t         *value;         /* Current value */
 
 
   DEBUG_printf(("ippAddRanges(ipp=%p, group=%02x(%s), name=\"%s\", "
                 "num_values=%d, lower=%p, upper=%p)", ipp, group,
                ippTagString(group), name, num_values, lower, upper));
 
-  if (!ipp || !name || num_values < 1)
-    return (NULL);
+ /*
+  * Range check input...
+  */
 
-  if ((attr = _ippAddAttr(ipp, num_values)) == NULL)
+  if (!ipp || !name || group < IPP_TAG_ZERO ||
+      group == IPP_TAG_END || group >= IPP_TAG_UNSUPPORTED_VALUE ||
+      num_values < 1)
     return (NULL);
 
-  attr->name      = _cupsStrAlloc(name);
-  attr->group_tag = group;
-  attr->value_tag = IPP_TAG_RANGE;
+ /*
+  * Create the attribute...
+  */
+
+  if ((attr = ipp_add_attr(ipp, name, group, IPP_TAG_RANGE, num_values)) == NULL)
+    return (NULL);
 
-  if (lower != NULL && upper != NULL)
-    for (i = 0, value = attr->values;
-        i < num_values;
-        i ++, value ++)
+  if (lower && upper)
+  {
+    for (i = num_values, value = attr->values;
+        i > 0;
+        i --, value ++)
     {
-      value->range.lower = lower[i];
-      value->range.upper = upper[i];
+      value->range.lower = *lower++;
+      value->range.upper = *upper++;
     }
+  }
 
   return (attr);
 }
@@ -628,6 +763,15 @@ ippAddRanges(ipp_t      *ipp,              /* I - IPP message */
 
 /*
  * 'ippAddResolution()' - Add a resolution value to an IPP message.
+ *
+ * The @code ipp@ parameter refers to an IPP message previously created using the
+ * @link ippNew@ or @link ippNewRequest@ functions.
+ *
+ * The @code group@ parameter specifies the IPP attribute group tag: none
+ * (@code IPP_TAG_ZERO@, for member attributes), document (@code IPP_TAG_DOCUMENT@),
+ * event notification (@code IPP_TAG_EVENT_NOTIFICATION@), operation
+ * (@code IPP_TAG_OPERATION@), printer (@code IPP_TAG_PRINTER@), subscription
+ * (@code IPP_TAG_SUBSCRIPTION@), or unsupported (@code IPP_TAG_UNSUPPORTED_GROUP@).
  */
 
 ipp_attribute_t *                      /* O - New attribute */
@@ -645,15 +789,23 @@ ippAddResolution(ipp_t      *ipp, /* I - IPP message */
                 "units=%d, xres=%d, yres=%d)", ipp, group,
                ippTagString(group), name, units, xres, yres));
 
-  if (!ipp || !name)
+ /*
+  * Range check input...
+  */
+
+  if (!ipp || !name || group < IPP_TAG_ZERO ||
+      group == IPP_TAG_END || group >= IPP_TAG_UNSUPPORTED_VALUE ||
+      units < IPP_RES_PER_INCH || units > IPP_RES_PER_CM ||
+      xres < 0 || yres < 0)
     return (NULL);
 
-  if ((attr = _ippAddAttr(ipp, 1)) == NULL)
+ /*
+  * Create the attribute...
+  */
+
+  if ((attr = ipp_add_attr(ipp, name, group, IPP_TAG_RESOLUTION, 1)) == NULL)
     return (NULL);
 
-  attr->name                       = _cupsStrAlloc(name);
-  attr->group_tag                  = group;
-  attr->value_tag                  = IPP_TAG_RESOLUTION;
   attr->values[0].resolution.xres  = xres;
   attr->values[0].resolution.yres  = yres;
   attr->values[0].resolution.units = units;
@@ -664,6 +816,15 @@ ippAddResolution(ipp_t      *ipp,  /* I - IPP message */
 
 /*
  * 'ippAddResolutions()' - Add resolution values to an IPP message.
+ *
+ * The @code ipp@ parameter refers to an IPP message previously created using the
+ * @link ippNew@ or @link ippNewRequest@ functions.
+ *
+ * The @code group@ parameter specifies the IPP attribute group tag: none
+ * (@code IPP_TAG_ZERO@, for member attributes), document (@code IPP_TAG_DOCUMENT@),
+ * event notification (@code IPP_TAG_EVENT_NOTIFICATION@), operation
+ * (@code IPP_TAG_OPERATION@), printer (@code IPP_TAG_PRINTER@), subscription
+ * (@code IPP_TAG_SUBSCRIPTION@), or unsupported (@code IPP_TAG_UNSUPPORTED_GROUP@).
  */
 
 ipp_attribute_t *                      /* O - New attribute */
@@ -677,32 +838,41 @@ ippAddResolutions(ipp_t      *ipp,        /* I - IPP message */
 {
   int                  i;              /* Looping var */
   ipp_attribute_t      *attr;          /* New attribute */
-  ipp_value_t          *value;         /* Current value */
+  _ipp_value_t         *value;         /* Current value */
 
 
   DEBUG_printf(("ippAddResolutions(ipp=%p, group=%02x(%s), name=\"%s\", "
                 "num_value=%d, units=%d, xres=%p, yres=%p)", ipp, group,
                ippTagString(group), name, num_values, units, xres, yres));
 
-  if (!ipp || !name || num_values < 1)
-    return (NULL);
+ /*
+  * Range check input...
+  */
 
-  if ((attr = _ippAddAttr(ipp, num_values)) == NULL)
+  if (!ipp || !name || group < IPP_TAG_ZERO ||
+      group == IPP_TAG_END || group >= IPP_TAG_UNSUPPORTED_VALUE ||
+      num_values < 1 ||
+      units < IPP_RES_PER_INCH || units > IPP_RES_PER_CM)
     return (NULL);
 
-  attr->name      = _cupsStrAlloc(name);
-  attr->group_tag = group;
-  attr->value_tag = IPP_TAG_RESOLUTION;
+ /*
+  * Create the attribute...
+  */
+
+  if ((attr = ipp_add_attr(ipp, name, group, IPP_TAG_RESOLUTION, num_values)) == NULL)
+    return (NULL);
 
-  if (xres != NULL && yres != NULL)
-    for (i = 0, value = attr->values;
-        i < num_values;
-        i ++, value ++)
+  if (xres && yres)
+  {
+    for (i = num_values, value = attr->values;
+        i > 0;
+        i --, value ++)
     {
-      value->resolution.xres  = xres[i];
-      value->resolution.yres  = yres[i];
+      value->resolution.xres  = *xres++;
+      value->resolution.yres  = *yres++;
       value->resolution.units = units;
     }
+  }
 
   return (attr);
 }
@@ -710,504 +880,1571 @@ ippAddResolutions(ipp_t      *ipp,     /* I - IPP message */
 
 /*
  * 'ippAddSeparator()' - Add a group separator to an IPP message.
+ *
+ * The @code ipp@ parameter refers to an IPP message previously created using the
+ * @link ippNew@ or @link ippNewRequest@ functions.
  */
 
 ipp_attribute_t *                      /* O - New attribute */
 ippAddSeparator(ipp_t *ipp)            /* I - IPP message */
 {
-  ipp_attribute_t      *attr;          /* New attribute */
-
-
   DEBUG_printf(("ippAddSeparator(ipp=%p)", ipp));
 
-  if (!ipp)
-    return (NULL);
+ /*
+  * Range check input...
+  */
 
-  if ((attr = _ippAddAttr(ipp, 0)) == NULL)
+  if (!ipp)
     return (NULL);
 
-  attr->group_tag = IPP_TAG_ZERO;
-  attr->value_tag = IPP_TAG_ZERO;
+ /*
+  * Create the attribute...
+  */
 
-  return (attr);
+  return (ipp_add_attr(ipp, NULL, IPP_TAG_ZERO, IPP_TAG_ZERO, 0));
 }
 
 
 /*
- * 'ippDateToTime()' - Convert from RFC 1903 Date/Time format to UNIX time
- *                     in seconds.
+ * 'ippAddString()' - Add a language-encoded string to an IPP message.
+ *
+ * The @code ipp@ parameter refers to an IPP message previously created using the
+ * @link ippNew@ or @link ippNewRequest@ functions.
+ *
+ * The @code group@ parameter specifies the IPP attribute group tag: none
+ * (@code IPP_TAG_ZERO@, for member attributes), document (@code IPP_TAG_DOCUMENT@),
+ * event notification (@code IPP_TAG_EVENT_NOTIFICATION@), operation
+ * (@code IPP_TAG_OPERATION@), printer (@code IPP_TAG_PRINTER@), subscription
+ * (@code IPP_TAG_SUBSCRIPTION@), or unsupported (@code IPP_TAG_UNSUPPORTED_GROUP@).
+ *
+ * Supported string values include charset (@code IPP_TAG_CHARSET@), keyword
+ * (@code IPP_TAG_KEYWORD@), language (@code IPP_TAG_LANGUAGE@), mimeMediaType
+ * (@code IPP_TAG_MIMETYPE@), name (@code IPP_TAG_NAME@), nameWithLanguage
+ * (@code IPP_TAG_NAMELANG), text (@code IPP_TAG_TEXT@), textWithLanguage
+ * (@code IPP_TAG_TEXTLANG@), uri (@code IPP_TAG_URI@), and uriScheme
+ * (@code IPP_TAG_URISCHEME@).
+ *
+ * The @code language@ parameter must be non-@code NULL@ for nameWithLanguage and
+ * textWithLanguage string values and must be @code NULL@ for all other string values.
  */
 
-time_t                                 /* O - UNIX time value */
-ippDateToTime(const ipp_uchar_t *date) /* I - RFC 1903 date info */
+ipp_attribute_t *                      /* O - New attribute */
+ippAddString(ipp_t      *ipp,          /* I - IPP message */
+             ipp_tag_t  group,         /* I - IPP group */
+            ipp_tag_t  value_tag,      /* I - Type of attribute */
+             const char *name,         /* I - Name of attribute */
+             const char *language,     /* I - Language code */
+             const char *value)                /* I - Value */
 {
-  struct tm    unixdate;               /* UNIX date/time info */
-  time_t       t;                      /* Computed time */
-
+  ipp_tag_t            temp_tag;       /* Temporary value tag (masked) */
+  ipp_attribute_t      *attr;          /* New attribute */
+  char                 code[32];       /* Charset/language code buffer */
 
-  if (!date)
-    return (0);
 
-  memset(&unixdate, 0, sizeof(unixdate));
+  DEBUG_printf(("ippAddString(ipp=%p, group=%02x(%s), value_tag=%02x(%s), "
+                "name=\"%s\", language=\"%s\", value=\"%s\")", ipp,
+               group, ippTagString(group), value_tag, ippTagString(value_tag), name,
+               language, value));
 
  /*
-  * RFC-1903 date/time format is:
-  *
-  *    Byte(s)  Description
-  *    -------  -----------
-  *    0-1      Year (0 to 65535)
-  *    2        Month (1 to 12)
-  *    3        Day (1 to 31)
-  *    4        Hours (0 to 23)
-  *    5        Minutes (0 to 59)
-  *    6        Seconds (0 to 60, 60 = "leap second")
-  *    7        Deciseconds (0 to 9)
-  *    8        +/- UTC
-  *    9        UTC hours (0 to 11)
-  *    10       UTC minutes (0 to 59)
+  * Range check input...
   */
 
-  unixdate.tm_year = ((date[0] << 8) | date[1]) - 1900;
-  unixdate.tm_mon  = date[2] - 1;
-  unixdate.tm_mday = date[3];
-  unixdate.tm_hour = date[4];
-  unixdate.tm_min  = date[5];
-  unixdate.tm_sec  = date[6];
-
-  t = mktime(&unixdate);
-
-  if (date[8] == '-')
-    t += date[9] * 3600 + date[10] * 60;
-  else
-    t -= date[9] * 3600 + date[10] * 60;
-
-  return (t);
-}
+  temp_tag = (ipp_tag_t)((int)value_tag & IPP_TAG_MASK);
 
+#if 0
+  if (!ipp || !name || group < IPP_TAG_ZERO ||
+      group == IPP_TAG_END || group >= IPP_TAG_UNSUPPORTED_VALUE ||
+      (temp_tag < IPP_TAG_TEXT && temp_tag != IPP_TAG_TEXTLANG &&
+       temp_tag != IPP_TAG_NAMELANG) || temp_tag > IPP_TAG_MIMETYPE)
+    return (NULL);
 
-/*
- * 'ippDelete()' - Delete an IPP message.
- */
+  if ((temp_tag == IPP_TAG_TEXTLANG || temp_tag == IPP_TAG_NAMELANG)
+          != (language != NULL))
+    return (NULL);
+#else
+  if (!ipp || !name || group < IPP_TAG_ZERO ||
+      group == IPP_TAG_END || group >= IPP_TAG_UNSUPPORTED_VALUE)
+    return (NULL);
+#endif /* 0 */
 
-void
-ippDelete(ipp_t *ipp)                  /* I - IPP message */
-{
-  ipp_attribute_t      *attr,          /* Current attribute */
-                       *next;          /* Next attribute */
+ /*
+  * See if we need to map charset, language, or locale values...
+  */
 
+  if (language && ((int)value_tag & IPP_TAG_COPY) &&
+      strcmp(language, ipp_lang_code(language, code, sizeof(code))))
+    value_tag = temp_tag;              /* Don't do a fast copy */
+  else if (value && value_tag == (ipp_tag_t)(IPP_TAG_CHARSET | IPP_TAG_COPY) &&
+           strcmp(value, ipp_get_code(value, code, sizeof(code))))
+    value_tag = temp_tag;              /* Don't do a fast copy */
+  else if (value && value_tag == (ipp_tag_t)(IPP_TAG_LANGUAGE | IPP_TAG_COPY) &&
+           strcmp(value, ipp_lang_code(value, code, sizeof(code))))
+    value_tag = temp_tag;              /* Don't do a fast copy */
 
-  DEBUG_printf(("ippDelete(ipp=%p)", ipp));
+ /*
+  * Create the attribute...
+  */
 
-  if (!ipp)
-    return;
+  if ((attr = ipp_add_attr(ipp, name, group, value_tag, 1)) == NULL)
+    return (NULL);
 
-  ipp->use --;
-  if (ipp->use > 0)
-    return;
+ /*
+  * Initialize the attribute data...
+  */
 
-  for (attr = ipp->attrs; attr != NULL; attr = next)
+  if ((int)value_tag & IPP_TAG_COPY)
   {
-    next = attr->next;
-    _ippFreeAttr(attr);
+    attr->values[0].string.language = (char *)language;
+    attr->values[0].string.text     = (char *)value;
+  }
+  else
+  {
+    if (language)
+      attr->values[0].string.language = _cupsStrAlloc(ipp_lang_code(language, code,
+                                                     sizeof(code)));
+
+    if (value_tag == IPP_TAG_CHARSET)
+      attr->values[0].string.text = _cupsStrAlloc(ipp_get_code(value, code,
+                                                               sizeof(code)));
+    else if (value_tag == IPP_TAG_LANGUAGE)
+      attr->values[0].string.text = _cupsStrAlloc(ipp_lang_code(value, code,
+                                                                sizeof(code)));
+    else
+      attr->values[0].string.text = _cupsStrAlloc(value);
   }
 
-  free(ipp);
+  return (attr);
 }
 
 
 /*
- * 'ippDeleteAttribute()' - Delete a single attribute in an IPP message.
+ * 'ippAddStrings()' - Add language-encoded strings to an IPP message.
  *
- * @since CUPS 1.1.19/Mac OS X 10.3@
+ * The @code ipp@ parameter refers to an IPP message previously created using the
+ * @link ippNew@ or @link ippNewRequest@ functions.
+ *
+ * The @code group@ parameter specifies the IPP attribute group tag: none
+ * (@code IPP_TAG_ZERO@, for member attributes), document (@code IPP_TAG_DOCUMENT@),
+ * event notification (@code IPP_TAG_EVENT_NOTIFICATION@), operation
+ * (@code IPP_TAG_OPERATION@), printer (@code IPP_TAG_PRINTER@), subscription
+ * (@code IPP_TAG_SUBSCRIPTION@), or unsupported (@code IPP_TAG_UNSUPPORTED_GROUP@).
+ *
+ * Supported string values include charset (@code IPP_TAG_CHARSET@), keyword
+ * (@code IPP_TAG_KEYWORD@), language (@code IPP_TAG_LANGUAGE@), mimeMediaType
+ * (@code IPP_TAG_MIMETYPE@), name (@code IPP_TAG_NAME@), nameWithLanguage
+ * (@code IPP_TAG_NAMELANG), text (@code IPP_TAG_TEXT@), textWithLanguage
+ * (@code IPP_TAG_TEXTLANG@), uri (@code IPP_TAG_URI@), and uriScheme
+ * (@code IPP_TAG_URISCHEME@).
+ *
+ * The @code language@ parameter must be non-@code NULL@ for nameWithLanguage and
+ * textWithLanguage string values and must be @code NULL@ for all other string values.
  */
 
-void
-ippDeleteAttribute(
-    ipp_t           *ipp,              /* I - IPP message */
-    ipp_attribute_t *attr)             /* I - Attribute to delete */
+ipp_attribute_t *                      /* O - New attribute */
+ippAddStrings(
+    ipp_t              *ipp,           /* I - IPP message */
+    ipp_tag_t          group,          /* I - IPP group */
+    ipp_tag_t          value_tag,      /* I - Type of attribute */
+    const char         *name,          /* I - Name of attribute */
+    int                num_values,     /* I - Number of values */
+    const char         *language,      /* I - Language code (@code NULL@ for default) */
+    const char * const *values)                /* I - Values */
 {
-  ipp_attribute_t      *current,       /* Current attribute */
-                       *prev;          /* Previous attribute */
+  int                  i;              /* Looping var */
+  ipp_tag_t            temp_tag;       /* Temporary value tag (masked) */
+  ipp_attribute_t      *attr;          /* New attribute */
+  _ipp_value_t         *value;         /* Current value */
+  char                 code[32];       /* Language/charset value buffer */
 
 
-  DEBUG_printf(("ippDeleteAttribute(ipp=%p, attr=%p(%s))", ipp, attr,
-                attr ? attr->name : "(null)"));
+  DEBUG_printf(("ippAddStrings(ipp=%p, group=%02x(%s), value_tag=%02x(%s), "
+                "name=\"%s\", num_values=%d, language=\"%s\", values=%p)", ipp,
+               group, ippTagString(group), value_tag, ippTagString(value_tag), name,
+               num_values, language, values));
 
  /*
-  * Find the attribute in the list...
+  * Range check input...
   */
 
-  for (current = ipp->attrs, prev = NULL;
-       current != NULL && current != attr;
-       prev = current, current = current->next);
-
-  if (current)
-  {
-   /*
-    * Found it, remove the attribute from the list...
-    */
+  temp_tag = (ipp_tag_t)((int)value_tag & IPP_TAG_MASK);
 
-    if (prev)
-      prev->next = current->next;
-    else
-      ipp->attrs = current->next;
+#if 0
+  if (!ipp || !name || group < IPP_TAG_ZERO ||
+      group == IPP_TAG_END || group >= IPP_TAG_UNSUPPORTED_VALUE ||
+      (temp_tag < IPP_TAG_TEXT && temp_tag != IPP_TAG_TEXTLANG &&
+       temp_tag != IPP_TAG_NAMELANG) || temp_tag > IPP_TAG_MIMETYPE ||
+      num_values < 1)
+    return (NULL);
 
-    if (current == ipp->last)
-      ipp->last = prev;
+  if ((temp_tag == IPP_TAG_TEXTLANG || temp_tag == IPP_TAG_NAMELANG)
+          != (language != NULL))
+    return (NULL);
+#else
+  if (!ipp || !name || group < IPP_TAG_ZERO ||
+      group == IPP_TAG_END || group >= IPP_TAG_UNSUPPORTED_VALUE ||
+      num_values < 1)
+    return (NULL);
+#endif /* 0 */
 
  /*
-    * Free memory used by the attribute...
-    */
+ /*
+  * See if we need to map charset, language, or locale values...
+  */
 
-    _ippFreeAttr(current);
+  if (language && ((int)value_tag & IPP_TAG_COPY) &&
+      strcmp(language, ipp_lang_code(language, code, sizeof(code))))
+    value_tag = temp_tag;              /* Don't do a fast copy */
+  else if (values && value_tag == (ipp_tag_t)(IPP_TAG_CHARSET | IPP_TAG_COPY))
+  {
+    for (i = 0; i < num_values; i ++)
+      if (strcmp(values[i], ipp_get_code(values[i], code, sizeof(code))))
+      {
+       value_tag = temp_tag;           /* Don't do a fast copy */
+        break;
+      }
+  }
+  else if (values && value_tag == (ipp_tag_t)(IPP_TAG_LANGUAGE | IPP_TAG_COPY))
+  {
+    for (i = 0; i < num_values; i ++)
+      if (strcmp(values[i], ipp_lang_code(values[i], code, sizeof(code))))
+      {
+       value_tag = temp_tag;           /* Don't do a fast copy */
+        break;
+      }
   }
-}
-
-
-/*
- * 'ippFindAttribute()' - Find a named attribute in a request...
- */
 
-ipp_attribute_t        *                       /* O - Matching attribute */
-ippFindAttribute(ipp_t      *ipp,      /* I - IPP message */
-                 const char *name,     /* I - Name of attribute */
-                ipp_tag_t  type)       /* I - Type of attribute */
-{
-  DEBUG_printf(("2ippFindAttribute(ipp=%p, name=\"%s\", type=%02x(%s))", ipp,
-                name, type, ippTagString(type)));
+ /*
+  * Create the attribute...
+  */
 
-  if (!ipp || !name)
+  if ((attr = ipp_add_attr(ipp, name, group, value_tag, num_values)) == NULL)
     return (NULL);
 
  /*
-  * Reset the current pointer...
+  * Initialize the attribute data...
   */
 
-  ipp->current = NULL;
+  for (i = num_values, value = attr->values;
+       i > 0;
+       i --, value ++)
+  {
+    if (language)
+    {
+      if (value == attr->values)
+      {
+        if ((int)value_tag & IPP_TAG_COPY)
+          value->string.language = (char *)language;
+        else
+          value->string.language = _cupsStrAlloc(ipp_lang_code(language, code,
+                                                               sizeof(code)));
+      }
+      else
+       value->string.language = attr->values[0].string.language;
+    }
 
- /*
-  * Search for the attribute...
-  */
+    if (values)
+    {
+      if ((int)value_tag & IPP_TAG_COPY)
+        value->string.text = (char *)*values++;
+      else if (value_tag == IPP_TAG_CHARSET)
+       value->string.text = _cupsStrAlloc(ipp_get_code(*values++, code, sizeof(code)));
+      else if (value_tag == IPP_TAG_LANGUAGE)
+       value->string.text = _cupsStrAlloc(ipp_lang_code(*values++, code, sizeof(code)));
+      else
+       value->string.text = _cupsStrAlloc(*values++);
+    }
+  }
 
-  return (ippFindNextAttribute(ipp, name, type));
+  return (attr);
 }
 
 
 /*
- * 'ippFindNextAttribute()' - Find the next named attribute in a request...
+ * 'ippCopyAttribute()' - Copy an attribute.
+ *
+ * The specified attribute, @code attr@, is copied to the destination IPP message.
+ * When @code quickcopy@ is non-zero, a "shallow" reference copy of the attribute is
+ * created - this should only be done as long as the original source IPP message will
+ * not be freed for the life of the destination.
+ *
+ * @since CUPS 1.6@
  */
 
-ipp_attribute_t        *                       /* O - Matching attribute */
-ippFindNextAttribute(ipp_t      *ipp,  /* I - IPP message */
-                     const char *name, /* I - Name of attribute */
-                    ipp_tag_t  type)   /* I - Type of attribute */
+
+ipp_attribute_t *                      /* O - New attribute */
+ippCopyAttribute(
+    ipp_t           *dst,              /* I - Destination IPP message */
+    ipp_attribute_t *srcattr,          /* I - Attribute to copy */
+    int             quickcopy)         /* I - 1 for a referenced copy, 0 for normal */
 {
-  ipp_attribute_t      *attr;          /* Current atttribute */
-  ipp_tag_t            value_tag;      /* Value tag */
+  int                  i;              /* Looping var */
+  ipp_attribute_t      *dstattr;       /* Destination attribute */
+  _ipp_value_t         *srcval,        /* Source value */
+                       *dstval;        /* Destination value */
 
 
-  DEBUG_printf(("2ippFindNextAttribute(ipp=%p, name=\"%s\", type=%02x(%s))",
-                ipp, name, type, ippTagString(type)));
+  DEBUG_printf(("ippCopyAttribute(dst=%p, srcattr=%p, quickcopy=%d)", dst, srcattr,
+                quickcopy));
 
-  if (!ipp || !name)
+ /*
+  * Range check input...
+  */
+
+  if (!dst || !srcattr)
     return (NULL);
 
-  if (ipp->current)
-  {
-    ipp->prev = ipp->current;
-    attr      = ipp->current->next;
-  }
-  else
-  {
-    ipp->prev = NULL;
-    attr      = ipp->attrs;
-  }
+ /*
+  * Copy it...
+  */
 
-  for (; attr != NULL; ipp->prev = attr, attr = attr->next)
+  quickcopy = quickcopy ? IPP_TAG_COPY : 0;
+
+  switch (srcattr->value_tag & ~IPP_TAG_COPY)
   {
-    DEBUG_printf(("4ippFindAttribute: attr=%p, name=\"%s\"", attr,
-                  attr->name));
+    case IPP_TAG_ZERO :
+        dstattr = ippAddSeparator(dst);
+       break;
 
-    value_tag = (ipp_tag_t)(attr->value_tag & IPP_TAG_MASK);
+    case IPP_TAG_INTEGER :
+    case IPP_TAG_ENUM :
+        dstattr = ippAddIntegers(dst, srcattr->group_tag, srcattr->value_tag,
+                                srcattr->name, srcattr->num_values, NULL);
+        if (!dstattr)
+          break;
+
+        for (i = srcattr->num_values, srcval = srcattr->values, dstval = dstattr->values;
+             i > 0;
+             i --, srcval ++, dstval ++)
+         dstval->integer = srcval->integer;
+        break;
 
-    if (attr->name != NULL && _cups_strcasecmp(attr->name, name) == 0 &&
-        (value_tag == type || type == IPP_TAG_ZERO ||
-        (value_tag == IPP_TAG_TEXTLANG && type == IPP_TAG_TEXT) ||
-        (value_tag == IPP_TAG_NAMELANG && type == IPP_TAG_NAME)))
-    {
-      ipp->current = attr;
+    case IPP_TAG_BOOLEAN :
+        dstattr = ippAddBooleans(dst, srcattr->group_tag, srcattr->name,
+                               srcattr->num_values, NULL);
+        if (!dstattr)
+          break;
+
+        for (i = srcattr->num_values, srcval = srcattr->values, dstval = dstattr->values;
+             i > 0;
+             i --, srcval ++, dstval ++)
+         dstval->boolean = srcval->boolean;
+        break;
 
-      return (attr);
-    }
-  }
+    case IPP_TAG_TEXT :
+    case IPP_TAG_NAME :
+    case IPP_TAG_KEYWORD :
+    case IPP_TAG_URI :
+    case IPP_TAG_URISCHEME :
+    case IPP_TAG_CHARSET :
+    case IPP_TAG_LANGUAGE :
+    case IPP_TAG_MIMETYPE :
+        dstattr = ippAddStrings(dst, srcattr->group_tag,
+                               (ipp_tag_t)(srcattr->value_tag | quickcopy),
+                               srcattr->name, srcattr->num_values, NULL, NULL);
+        if (!dstattr)
+          break;
 
-  ipp->current = NULL;
-  ipp->prev    = NULL;
+        if (quickcopy)
+       {
+         for (i = srcattr->num_values, srcval = srcattr->values,
+                  dstval = dstattr->values;
+              i > 0;
+              i --, srcval ++, dstval ++)
+           dstval->string.text = srcval->string.text;
+        }
+       else if (srcattr->value_tag & IPP_TAG_COPY)
+       {
+         for (i = srcattr->num_values, srcval = srcattr->values,
+                  dstval = dstattr->values;
+              i > 0;
+              i --, srcval ++, dstval ++)
+           dstval->string.text = _cupsStrAlloc(srcval->string.text);
+       }
+       else
+       {
+         for (i = srcattr->num_values, srcval = srcattr->values,
+                  dstval = dstattr->values;
+              i > 0;
+              i --, srcval ++, dstval ++)
+           dstval->string.text = _cupsStrRetain(srcval->string.text);
+       }
+        break;
 
-  return (NULL);
-}
+    case IPP_TAG_DATE :
+        if (srcattr->num_values != 1)
+          return (NULL);
 
+        dstattr = ippAddDate(dst, srcattr->group_tag, srcattr->name,
+                            srcattr->values[0].date);
+        break;
 
-/*
- * 'ippLength()' - Compute the length of an IPP message.
- */
+    case IPP_TAG_RESOLUTION :
+        dstattr = ippAddResolutions(dst, srcattr->group_tag, srcattr->name,
+                                   srcattr->num_values, IPP_RES_PER_INCH,
+                                   NULL, NULL);
+        if (!dstattr)
+          break;
+
+        for (i = srcattr->num_values, srcval = srcattr->values, dstval = dstattr->values;
+             i > 0;
+             i --, srcval ++, dstval ++)
+       {
+         dstval->resolution.xres  = srcval->resolution.xres;
+         dstval->resolution.yres  = srcval->resolution.yres;
+         dstval->resolution.units = srcval->resolution.units;
+       }
+        break;
 
-size_t                                 /* O - Size of IPP message */
-ippLength(ipp_t *ipp)                  /* I - IPP message */
-{
-  return (ipp_length(ipp, 0));
-}
+    case IPP_TAG_RANGE :
+        dstattr = ippAddRanges(dst, srcattr->group_tag, srcattr->name,
+                              srcattr->num_values, NULL, NULL);
+        if (!dstattr)
+          break;
+
+        for (i = srcattr->num_values, srcval = srcattr->values, dstval = dstattr->values;
+             i > 0;
+             i --, srcval ++, dstval ++)
+       {
+         dstval->range.lower = srcval->range.lower;
+         dstval->range.upper = srcval->range.upper;
+       }
+        break;
 
+    case IPP_TAG_TEXTLANG :
+    case IPP_TAG_NAMELANG :
+        dstattr = ippAddStrings(dst, srcattr->group_tag,
+                               (ipp_tag_t)(srcattr->value_tag | quickcopy),
+                               srcattr->name, srcattr->num_values, NULL, NULL);
+        if (!dstattr)
+          break;
 
-/*
- * 'ippNew()' - Allocate a new IPP message.
- */
+        if (quickcopy)
+       {
+         for (i = srcattr->num_values, srcval = srcattr->values,
+                  dstval = dstattr->values;
+              i > 0;
+              i --, srcval ++, dstval ++)
+         {
+            dstval->string.language = srcval->string.language;
+           dstval->string.text     = srcval->string.text;
+          }
+        }
+       else if (srcattr->value_tag & IPP_TAG_COPY)
+       {
+         for (i = srcattr->num_values, srcval = srcattr->values,
+                  dstval = dstattr->values;
+              i > 0;
+              i --, srcval ++, dstval ++)
+         {
+           if (srcval == srcattr->values)
+              dstval->string.language = _cupsStrAlloc(srcval->string.language);
+           else
+              dstval->string.language = dstattr->values[0].string.language;
 
-ipp_t *                                        /* O - New IPP message */
-ippNew(void)
-{
-  ipp_t        *temp;                          /* New IPP message */
+           dstval->string.text = _cupsStrAlloc(srcval->string.text);
+          }
+        }
+       else
+       {
+         for (i = srcattr->num_values, srcval = srcattr->values,
+                  dstval = dstattr->values;
+              i > 0;
+              i --, srcval ++, dstval ++)
+         {
+           if (srcval == srcattr->values)
+              dstval->string.language = _cupsStrRetain(srcval->string.language);
+           else
+              dstval->string.language = dstattr->values[0].string.language;
 
+           dstval->string.text = _cupsStrRetain(srcval->string.text);
+          }
+        }
+        break;
 
-  DEBUG_puts("ippNew()");
+    case IPP_TAG_BEGIN_COLLECTION :
+        dstattr = ippAddCollections(dst, srcattr->group_tag, srcattr->name,
+                                   srcattr->num_values, NULL);
+        if (!dstattr)
+          break;
+
+        for (i = srcattr->num_values, srcval = srcattr->values, dstval = dstattr->values;
+             i > 0;
+             i --, srcval ++, dstval ++)
+       {
+         dstval->collection = srcval->collection;
+         srcval->collection->use ++;
+       }
+        break;
 
-  if ((temp = (ipp_t *)calloc(1, sizeof(ipp_t))) != NULL)
-  {
-   /*
-    * Default to IPP 1.1...
-    */
+    case IPP_TAG_STRING :
+    default :
+        /* TODO: Implement quick copy for unknown/octetString values */
+        dstattr = ippAddIntegers(dst, srcattr->group_tag, srcattr->value_tag,
+                                srcattr->name, srcattr->num_values, NULL);
+        if (!dstattr)
+          break;
+
+        for (i = srcattr->num_values, srcval = srcattr->values, dstval = dstattr->values;
+             i > 0;
+             i --, srcval ++, dstval ++)
+       {
+         dstval->unknown.length = srcval->unknown.length;
 
-    temp->request.any.version[0] = 1;
-    temp->request.any.version[1] = 1;
-    temp->use                    = 1;
+         if (dstval->unknown.length > 0)
+         {
+           if ((dstval->unknown.data = malloc(dstval->unknown.length)) == NULL)
+             dstval->unknown.length = 0;
+           else
+             memcpy(dstval->unknown.data, srcval->unknown.data, dstval->unknown.length);
+         }
+       }
+        break; /* anti-compiler-warning-code */
   }
 
-  DEBUG_printf(("1ippNew: Returning %p", temp));
-
-  return (temp);
+  return (dstattr);
 }
 
 
 /*
- *  'ippNewRequest()' - Allocate a new IPP request message.
+ * 'ippCopyAttributes()' - Copy attributes from one IPP message to another.
  *
- * The new request message is initialized with the attributes-charset and
- * attributes-natural-language attributes added. The
- * attributes-natural-language value is derived from the current locale.
+ * Zero or more attributes are copied from the source IPP message, @code@ src, to the
+ * destination IPP message, @code dst@. When @code quickcopy@ is non-zero, a "shallow"
+ * reference copy of the attribute is created - this should only be done as long as the
+ * original source IPP message will not be freed for the life of the destination.
  *
- * @since CUPS 1.2/Mac OS X 10.5@
+ * The @code cb@ and @code context@ parameters provide a generic way to "filter" the
+ * attributes that are copied - the function must return 1 to copy the attribute or
+ * 0 to skip it. The function may also choose to do a partial copy of the source attribute
+ * itself.
+ *
+ * @since CUPS 1.6@
  */
 
-ipp_t *                                        /* O - IPP request message */
-ippNewRequest(ipp_op_t op)             /* I - Operation code */
+int                                    /* O - 1 on success, 0 on error */
+ippCopyAttributes(
+    ipp_t        *dst,                 /* I - Destination IPP message */
+    ipp_t        *src,                 /* I - Source IPP message */
+    int          quickcopy,            /* I - 1 for a referenced copy, 0 for normal */
+    ipp_copycb_t cb,                   /* I - Copy callback or @code NULL@ for none */
+    void         *context)             /* I - Context pointer */
 {
-  ipp_t                *request;               /* IPP request message */
-  cups_lang_t  *language;              /* Current language localization */
+  ipp_attribute_t      *srcattr;       /* Source attribute */
 
 
-  DEBUG_printf(("ippNewRequest(op=%02x(%s))", op, ippOpString(op)));
+  DEBUG_printf(("ippCopyAttributes(dst=%p, src=%p, quickcopy=%d, cb=%p, context=%p)",
+                dst, src, quickcopy, cb, context));
 
  /*
-  * Create a new IPP message...
+  * Range check input...
   */
 
-  if ((request = ippNew()) == NULL)
-    return (NULL);
+  if (!dst || !src)
+    return (0);
 
  /*
-  * Set the operation and request ID...
+  * Loop through source attributes and copy as needed...
   */
 
-  request->request.op.operation_id = op;
-  request->request.op.request_id   = 1;
+  for (srcattr = src->attrs; srcattr; srcattr = srcattr->next)
+    if (!cb || (*cb)(context, dst, srcattr))
+      if (!ippCopyAttribute(dst, srcattr, quickcopy))
+        return (0);
 
- /*
-  * Use UTF-8 as the character set...
-  */
+  return (1);
+}
 
-  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
-               "attributes-charset", NULL, "utf-8");
 
- /*
-  * Get the language from the current locale...
-  */
+/*
+ * 'ippDateToTime()' - Convert from RFC 1903 Date/Time format to UNIX time
+ *                     in seconds.
+ */
 
-  language = cupsLangDefault();
+time_t                                 /* O - UNIX time value */
+ippDateToTime(const ipp_uchar_t *date) /* I - RFC 1903 date info */
+{
+  struct tm    unixdate;               /* UNIX date/time info */
+  time_t       t;                      /* Computed time */
 
-  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
-               "attributes-natural-language", NULL, language->language);
+
+  if (!date)
+    return (0);
+
+  memset(&unixdate, 0, sizeof(unixdate));
 
  /*
-  * Return the new request...
+  * RFC-1903 date/time format is:
+  *
+  *    Byte(s)  Description
+  *    -------  -----------
+  *    0-1      Year (0 to 65535)
+  *    2        Month (1 to 12)
+  *    3        Day (1 to 31)
+  *    4        Hours (0 to 23)
+  *    5        Minutes (0 to 59)
+  *    6        Seconds (0 to 60, 60 = "leap second")
+  *    7        Deciseconds (0 to 9)
+  *    8        +/- UTC
+  *    9        UTC hours (0 to 11)
+  *    10       UTC minutes (0 to 59)
   */
 
-  return (request);
+  unixdate.tm_year = ((date[0] << 8) | date[1]) - 1900;
+  unixdate.tm_mon  = date[2] - 1;
+  unixdate.tm_mday = date[3];
+  unixdate.tm_hour = date[4];
+  unixdate.tm_min  = date[5];
+  unixdate.tm_sec  = date[6];
+
+  t = mktime(&unixdate);
+
+  if (date[8] == '-')
+    t += date[9] * 3600 + date[10] * 60;
+  else
+    t -= date[9] * 3600 + date[10] * 60;
+
+  return (t);
 }
 
 
 /*
- * 'ippRead()' - Read data for an IPP message from a HTTP connection.
+ * 'ippDelete()' - Delete an IPP message.
  */
 
-ipp_state_t                            /* O - Current state */
-ippRead(http_t *http,                  /* I - HTTP connection */
-        ipp_t  *ipp)                   /* I - IPP data */
+void
+ippDelete(ipp_t *ipp)                  /* I - IPP message */
 {
-  DEBUG_printf(("ippRead(http=%p, ipp=%p), data_remaining=" CUPS_LLFMT,
-                http, ipp, CUPS_LLCAST (http ? http->data_remaining : -1)));
+  ipp_attribute_t      *attr,          /* Current attribute */
+                       *next;          /* Next attribute */
 
-  if (!http)
-    return (IPP_ERROR);
 
-  DEBUG_printf(("2ippRead: http->state=%d, http->used=%d", http->state,
-                http->used));
+  DEBUG_printf(("ippDelete(ipp=%p)", ipp));
 
-  return (ippReadIO(http, (ipp_iocb_t)ipp_read_http, http->blocking, NULL,
-                    ipp));
-}
+  if (!ipp)
+    return;
+
+  ipp->use --;
+  if (ipp->use > 0)
+    return;
 
+  for (attr = ipp->attrs; attr != NULL; attr = next)
+  {
+    next = attr->next;
 
-/*
- * 'ippReadFile()' - Read data for an IPP message from a file.
- *
- * @since CUPS 1.1.19/Mac OS X 10.3@
- */
+    ipp_free_values(attr, 0, attr->num_values);
 
-ipp_state_t                            /* O - Current state */
-ippReadFile(int   fd,                  /* I - HTTP data */
-            ipp_t *ipp)                        /* I - IPP data */
-{
-  DEBUG_printf(("ippReadFile(fd=%d, ipp=%p)", fd, ipp));
+    if (attr->name)
+      _cupsStrFree(attr->name);
 
-  return (ippReadIO(&fd, (ipp_iocb_t)ipp_read_file, 1, NULL, ipp));
+    free(attr);
+  }
+
+  free(ipp);
 }
 
 
 /*
- * 'ippReadIO()' - Read data for an IPP message.
+ * 'ippDeleteAttribute()' - Delete a single attribute in an IPP message.
  *
- * @since CUPS 1.2/Mac OS X 10.5@
+ * @since CUPS 1.1.19/Mac OS X 10.3@
  */
 
-ipp_state_t                            /* O - Current state */
-ippReadIO(void       *src,             /* I - Data source */
-          ipp_iocb_t cb,               /* I - Read callback function */
-         int        blocking,          /* I - Use blocking IO? */
-         ipp_t      *parent,           /* I - Parent request, if any */
-          ipp_t      *ipp)             /* I - IPP data */
+void
+ippDeleteAttribute(
+    ipp_t           *ipp,              /* I - IPP message */
+    ipp_attribute_t *attr)             /* I - Attribute to delete */
 {
-  int                  n;              /* Length of data */
-  unsigned char                *buffer,        /* Data buffer */
-                       string[IPP_MAX_NAME],
-                                       /* Small string buffer */
-                       *bufptr;        /* Pointer into buffer */
-  ipp_attribute_t      *attr;          /* Current attribute */
-  ipp_tag_t            tag;            /* Current tag */
-  ipp_tag_t            value_tag;      /* Current value tag */
-  ipp_value_t          *value;         /* Current value */
+  ipp_attribute_t      *current,       /* Current attribute */
+                       *prev;          /* Previous attribute */
 
 
-  DEBUG_printf(("ippReadIO(src=%p, cb=%p, blocking=%d, parent=%p, ipp=%p)",
-                src, cb, blocking, parent, ipp));
-  DEBUG_printf(("2ippReadIO: ipp->state=%d", ipp->state));
+  DEBUG_printf(("ippDeleteAttribute(ipp=%p, attr=%p(%s))", ipp, attr,
+                attr ? attr->name : "(null)"));
 
-  if (!src || !ipp)
-    return (IPP_ERROR);
+ /*
+  * Range check input...
+  */
 
-  if ((buffer = ipp_buffer_get()) == NULL)
-  {
-    DEBUG_puts("1ippReadIO: Unable to get read buffer.");
-    return (IPP_ERROR);
-  }
+  if (!attr)
+    return;
 
-  switch (ipp->state)
+ /*
+  * Find the attribute in the list...
+  */
+
+  if (ipp)
   {
-    case IPP_IDLE :
-        ipp->state ++; /* Avoid common problem... */
+    for (current = ipp->attrs, prev = NULL;
+        current;
+        prev = current, current = current->next)
+      if (current == attr)
+      {
+       /*
+       * Found it, remove the attribute from the list...
+       */
 
-    case IPP_HEADER :
-        if (parent == NULL)
-       {
-        /*
-          * Get the request header...
-         */
+       if (prev)
+         prev->next = current->next;
+       else
+         ipp->attrs = current->next;
 
-          if ((*cb)(src, buffer, 8) < 8)
-         {
-           DEBUG_puts("1ippReadIO: Unable to read header.");
-           ipp_buffer_release(buffer);
-           return (IPP_ERROR);
-         }
+       if (current == ipp->last)
+         ipp->last = prev;
 
-        /*
-          * Then copy the request header over...
-         */
+        break;
+      }
 
-          ipp->request.any.version[0]  = buffer[0];
-          ipp->request.any.version[1]  = buffer[1];
-          ipp->request.any.op_status   = (buffer[2] << 8) | buffer[3];
-          ipp->request.any.request_id  = (((((buffer[4] << 8) | buffer[5]) << 8) |
-                                        buffer[6]) << 8) | buffer[7];
+    if (!current)
+      return;
+  }
 
-          DEBUG_printf(("2ippReadIO: version=%d.%d", buffer[0], buffer[1]));
-         DEBUG_printf(("2ippReadIO: op_status=%04x",
-                       ipp->request.any.op_status));
-         DEBUG_printf(("2ippReadIO: request_id=%d",
-                       ipp->request.any.request_id));
-        }
+ /*
+  * Free memory used by the attribute...
+  */
 
-        ipp->state   = IPP_ATTRIBUTE;
-       ipp->current = NULL;
-       ipp->curtag  = IPP_TAG_ZERO;
-       ipp->prev    = ipp->last;
+  ipp_free_values(attr, 0, attr->num_values);
 
-       /*
-        * If blocking is disabled, stop here...
-       */
+  if (attr->name)
+    _cupsStrFree(attr->name);
 
-        if (!blocking)
-         break;
+  free(attr);
+}
 
-    case IPP_ATTRIBUTE :
-        for (;;)
-       {
-         if ((*cb)(src, buffer, 1) < 1)
-         {
-           DEBUG_puts("1ippReadIO: Callback returned EOF/error");
-           ipp_buffer_release(buffer);
-           return (IPP_ERROR);
-         }
 
-         DEBUG_printf(("2ippReadIO: ipp->current=%p, ipp->prev=%p",
-                       ipp->current, ipp->prev));
+/*
+ * 'ippDeleteValues()' - Delete values in an attribute.
+ *
+ * The @code element@ parameter specifies the first value to delete, starting at 0. It
+ * must be less than the number of values returned by @link ippGetCount@.
+ *
+ * Deleting all values in an attribute deletes the attribute.
+ *
+ * @since CUPS 1.6@
+ */
 
-        /*
-         * Read this attribute...
-         */
+int                                    /* O - 1 on success, 0 on failure */
+ippDeleteValues(
+    ipp_t           *ipp,              /* I - IPP message */
+    ipp_attribute_t *attr,             /* I - Attribute */
+    int             element,           /* I - Index of first value to delete (0-based) */
+    int             count)             /* I - Number of values to delete */
+{
+ /*
+  * Range check input...
+  */
 
-          tag = (ipp_tag_t)buffer[0];
+  if (!ipp || !attr || element < 0 || element >= attr->num_values || count <= 0 ||
+      (element + count) >= attr->num_values)
+    return (0);
 
-         if (tag == IPP_TAG_END)
-         {
-          /*
-           * No more attributes left...
-           */
+ /*
+  * If we are deleting all values, just delete the attribute entirely.
+  */
 
-            DEBUG_puts("2ippReadIO: IPP_TAG_END.");
+  if (count == attr->num_values)
+  {
+    ippDeleteAttribute(ipp, attr);
+    return (1);
+  }
 
-           ipp->state = IPP_DATA;
-           break;
-         }
-          else if (tag < IPP_TAG_UNSUPPORTED_VALUE)
-         {
-          /*
-           * Group tag...  Set the current group and continue...
-           */
+ /*
+  * Otherwise free the values in question and return.
+  */
 
-            if (ipp->curtag == tag)
-             ipp->prev = ippAddSeparator(ipp);
-            else if (ipp->current)
-             ipp->prev = ipp->current;
+  ipp_free_values(attr, element, count);
+
+  return (1);
+}
+
+
+/*
+ * 'ippFindAttribute()' - Find a named attribute in a request...
+ */
+
+ipp_attribute_t        *                       /* O - Matching attribute */
+ippFindAttribute(ipp_t      *ipp,      /* I - IPP message */
+                 const char *name,     /* I - Name of attribute */
+                ipp_tag_t  type)       /* I - Type of attribute */
+{
+  DEBUG_printf(("2ippFindAttribute(ipp=%p, name=\"%s\", type=%02x(%s))", ipp,
+                name, type, ippTagString(type)));
+
+  if (!ipp || !name)
+    return (NULL);
+
+ /*
+  * Reset the current pointer...
+  */
+
+  ipp->current = NULL;
+
+ /*
+  * Search for the attribute...
+  */
+
+  return (ippFindNextAttribute(ipp, name, type));
+}
+
+
+/*
+ * 'ippFindNextAttribute()' - Find the next named attribute in a request...
+ */
+
+ipp_attribute_t        *                       /* O - Matching attribute */
+ippFindNextAttribute(ipp_t      *ipp,  /* I - IPP message */
+                     const char *name, /* I - Name of attribute */
+                    ipp_tag_t  type)   /* I - Type of attribute */
+{
+  ipp_attribute_t      *attr;          /* Current atttribute */
+  ipp_tag_t            value_tag;      /* Value tag */
+
+
+  DEBUG_printf(("2ippFindNextAttribute(ipp=%p, name=\"%s\", type=%02x(%s))",
+                ipp, name, type, ippTagString(type)));
+
+  if (!ipp || !name)
+    return (NULL);
+
+  if (ipp->current)
+  {
+    ipp->prev = ipp->current;
+    attr      = ipp->current->next;
+  }
+  else
+  {
+    ipp->prev = NULL;
+    attr      = ipp->attrs;
+  }
+
+  for (; attr != NULL; ipp->prev = attr, attr = attr->next)
+  {
+    DEBUG_printf(("4ippFindAttribute: attr=%p, name=\"%s\"", attr,
+                  attr->name));
+
+    value_tag = (ipp_tag_t)(attr->value_tag & IPP_TAG_MASK);
+
+    if (attr->name != NULL && _cups_strcasecmp(attr->name, name) == 0 &&
+        (value_tag == type || type == IPP_TAG_ZERO ||
+        (value_tag == IPP_TAG_TEXTLANG && type == IPP_TAG_TEXT) ||
+        (value_tag == IPP_TAG_NAMELANG && type == IPP_TAG_NAME)))
+    {
+      ipp->current = attr;
+
+      return (attr);
+    }
+  }
+
+  ipp->current = NULL;
+  ipp->prev    = NULL;
+
+  return (NULL);
+}
+
+
+/*
+ * 'ippFirstAttribute()' - Return the first attribute in the message.
+ *
+ * @since CUPS 1.6@
+ */
+
+ipp_attribute_t        *                       /* O - First attribute or @code NULL@ if none */
+ippFirstAttribute(ipp_t *ipp)          /* I - IPP message */
+{
+ /*
+  * Range check input...
+  */
+
+  if (!ipp)
+    return (NULL);
+
+ /*
+  * Return the first attribute...
+  */
+
+  return (ipp->current = ipp->attrs);
+}
+
+
+/*
+ * 'ippGetBoolean()' - Get a boolean value for an attribute.
+ *
+ * The @code element@ parameter specifies which value to get from 0 to
+ * @link ippGetCount(attr)@ - 1.
+ *
+ * @since CUPS 1.6@
+ */
+
+int                                    /* O - Boolean value or -1 on error */
+ippGetBoolean(ipp_attribute_t *attr,   /* I - IPP attribute */
+              int             element) /* I - Value number (0-based) */
+{
+ /*
+  * Range check input...
+  */
+
+  if (!attr || attr->value_tag != IPP_TAG_BOOLEAN ||
+      element < 0 || element >= attr->num_values)
+    return (-1);
+
+ /*
+  * Return the value...
+  */
+
+  return (attr->values[element].boolean);
+}
+
+
+/*
+ * 'ippGetCollection()' - Get a collection value for an attribute.
+ *
+ * The @code element@ parameter specifies which value to get from 0 to
+ * @link ippGetCount(attr)@ - 1.
+ *
+ * @since CUPS 1.6@
+ */
+
+ipp_t *                                        /* O - Collection value or @code NULL@ on error */
+ippGetCollection(
+    ipp_attribute_t *attr,             /* I - IPP attribute */
+    int             element)           /* I - Value number (0-based) */
+{
+ /*
+  * Range check input...
+  */
+
+  if (!attr || attr->value_tag != IPP_TAG_BEGIN_COLLECTION ||
+      element < 0 || element >= attr->num_values)
+    return (NULL);
+
+ /*
+  * Return the value...
+  */
+
+  return (attr->values[element].collection);
+}
+
+
+/*
+ * 'ippGetCount()' - Get the number of values in an attribute.
+ *
+ * @since CUPS 1.6@
+ */
+
+int                                    /* O - Number of values or -1 on error */
+ippGetCount(ipp_attribute_t *attr)     /* I - IPP attribute */
+{
+ /*
+  * Range check input...
+  */
+
+  if (!attr)
+    return (-1);
+
+ /*
+  * Return the number of values...
+  */
+
+  return (attr->num_values);
+}
+
+
+/*
+ * 'ippGetGroupTag()' - Get the group associated with an attribute.
+ *
+ * @since CUPS 1.6@
+ */
+
+ipp_tag_t                              /* O - Group tag or @code IPP_TAG_ZERO@ on error */
+ippGetGroupTag(ipp_attribute_t *attr)  /* I - IPP attribute */
+{
+ /*
+  * Range check input...
+  */
+
+  if (!attr)
+    return (IPP_TAG_ZERO);
+
+ /*
+  * Return the group...
+  */
+
+  return (attr->group_tag);
+}
+
+
+/*
+ * 'ippGetInteger()' - Get the integer/enum value for an attribute.
+ *
+ * The @code element@ parameter specifies which value to get from 0 to
+ * @link ippGetCount(attr)@ - 1.
+ *
+ * @since CUPS 1.6@
+ */
+
+int                                    /* O - Value or -1 on error */
+ippGetInteger(ipp_attribute_t *attr,   /* I - IPP attribute */
+              int             element) /* I - Value number (0-based) */
+{
+ /*
+  * Range check input...
+  */
+
+  if (!attr || (attr->value_tag != IPP_TAG_INTEGER && attr->value_tag != IPP_TAG_ENUM) ||
+      element < 0 || element >= attr->num_values)
+    return (-1);
+
+ /*
+  * Return the value...
+  */
+
+  return (attr->values[element].integer);
+}
+
+
+/*
+ * 'ippGetName()' - Get the attribute name.
+ *
+ * @since CUPS 1.6@
+ */
+
+const char *                           /* O - Attribute name or @code NULL@ for separators */
+ippGetName(ipp_attribute_t *attr)      /* I - IPP attribute */
+{
+ /*
+  * Range check input...
+  */
+
+  if (!attr)
+    return (NULL);
+
+ /*
+  * Return the name...
+  */
+
+  return (attr->name);
+}
+
+
+/*
+ * 'ippGetOperation()' - Get the operation ID in an IPP message.
+ *
+ * @since CUPS 1.6@
+ */
+
+ipp_op_t                               /* O - Operation ID or -1 on error */
+ippGetOperation(ipp_t *ipp)            /* I - IPP request message */
+{
+ /*
+  * Range check input...
+  */
+
+  if (!ipp)
+    return ((ipp_op_t)-1);
+
+ /*
+  * Return the value...
+  */
+
+  return (ipp->request.op.operation_id);
+}
+
+
+/*
+ * 'ippGetRequestId()' - Get the request ID from an IPP message.
+ *
+ * @since CUPS 1.6@
+ */
+
+int                                    /* O - Request ID or -1 on error */
+ippGetRequestId(ipp_t *ipp)            /* I - IPP message */
+{
+ /*
+  * Range check input...
+  */
+
+  if (!ipp)
+    return (-1);
+
+ /*
+  * Return the request ID...
+  */
+
+  return (ipp->request.any.request_id);
+}
+
+
+/*
+ * 'ippGetResolution()' - Get a resolution value for an attribute.
+ *
+ * The @code element@ parameter specifies which value to get from 0 to
+ * @link ippGetCount(attr)@ - 1.
+ *
+ * @since CUPS 1.6@
+ */
+
+int                                    /* O - Horizontal/cross feed resolution or -1 */
+ippGetResolution(
+    ipp_attribute_t *attr,             /* I - IPP attribute */
+    int             element,           /* I - Value number (0-based) */
+    int             *yres,             /* O - Vertical/feed resolution */
+    ipp_res_t       *units)            /* O - Units for resolution */
+{
+ /*
+  * Range check input...
+  */
+
+  if (!attr || attr->value_tag != IPP_TAG_RESOLUTION ||
+      element < 0 || element >= attr->num_values)
+    return (-1);
+
+ /*
+  * Return the value...
+  */
+
+  if (yres)
+    *yres = attr->values[element].resolution.yres;
+
+  if (units)
+    *units = attr->values[element].resolution.units;
+
+  return (attr->values[element].resolution.xres);
+}
+
+
+/*
+ * 'ippGetStatusCode()' - Get the status code from an IPP response or event message.
+ *
+ * @since CUPS 1.6@
+ */
+
+ipp_status_t                           /* O - Status code in IPP message */
+ippGetStatusCode(ipp_t *ipp)           /* I - IPP response or event message */
+{
+ /*
+  * Range check input...
+  */
+
+  if (!ipp)
+    return (IPP_INTERNAL_ERROR);
+
+ /*
+  * Return the value...
+  */
+
+  return (ipp->request.status.status_code);
+}
+
+
+/*
+ * 'ippGetString()' - Get the string and optionally the language code for an attribute.
+ *
+ * The @code element@ parameter specifies which value to get from 0 to
+ * @link ippGetCount(attr)@ - 1.
+ *
+ * @since CUPS 1.6@
+ */
+
+const char *
+ippGetString(ipp_attribute_t *attr,    /* I - IPP attribute */
+             int             element,  /* I - Value number (0-based) */
+            const char      **language)/* O - Language code (@code NULL@ for don't care) */
+{
+ /*
+  * Range check input...
+  */
+
+  if (!attr || element < 0 || element >= attr->num_values ||
+      (attr->value_tag != IPP_TAG_TEXTLANG && attr->value_tag != IPP_TAG_NAMELANG &&
+       (attr->value_tag < IPP_TAG_TEXT || attr->value_tag > IPP_TAG_MIMETYPE)))
+    return (NULL);
+
+ /*
+  * Return the value...
+  */
+
+  if (language)
+    *language = attr->values[element].string.language;
+
+  return (attr->values[element].string.text);
+}
+
+
+/*
+ * 'ippGetValueTag()' - Get the value tag for an attribute.
+ *
+ * @since CUPS 1.6@
+ */
+
+ipp_tag_t                              /* O - Value tag or @code IPP_TAG_ZERO@ on error */
+ippGetValueTag(ipp_attribute_t *attr)  /* I - IPP attribute */
+{
+ /*
+  * Range check input...
+  */
+
+  if (!attr)
+    return (IPP_TAG_ZERO);
+
+ /*
+  * Return the value...
+  */
+
+  return (attr->value_tag);
+}
+
+
+/*
+ * 'ippGetVersion()' - Get the major and minor version number from an IPP message.
+ *
+ * @since CUPS 1.6@
+ */
+
+int                                    /* O - Major version number or -1 on error */
+ippGetVersion(ipp_t *ipp,              /* I - IPP message */
+              int   *minor)            /* O - Minor version number or @code NULL@ */
+{
+ /*
+  * Range check input...
+  */
+
+  if (!ipp)
+  {
+    if (minor)
+      *minor = -1;
+
+    return (-1);
+  }
+
+ /*
+  * Return the value...
+  */
+
+  if (minor)
+    *minor = ipp->request.any.version[1];
+
+  return (ipp->request.any.version[0]);
+}
+
+
+/*
+ * 'ippLength()' - Compute the length of an IPP message.
+ */
+
+size_t                                 /* O - Size of IPP message */
+ippLength(ipp_t *ipp)                  /* I - IPP message */
+{
+  return (ipp_length(ipp, 0));
+}
+
+
+/*
+ * 'ippNextAttribute()' - Return the next attribute in the message.
+ *
+ * @since CUPS 1.6@
+ */
+
+ipp_attribute_t *                      /* O - Next attribute or @code NULL@ if none */
+ippNextAttribute(ipp_t *ipp)           /* I - IPP message */
+{
+ /*
+  * Range check input...
+  */
+
+  if (!ipp || !ipp->current)
+    return (NULL);
+
+ /*
+  * Return the next attribute...
+  */
+
+  return (ipp->current = ipp->current->next);
+}
+
+
+/*
+ * 'ippNew()' - Allocate a new IPP message.
+ */
+
+ipp_t *                                        /* O - New IPP message */
+ippNew(void)
+{
+  ipp_t        *temp;                          /* New IPP message */
+
+
+  DEBUG_puts("ippNew()");
+
+  if ((temp = (ipp_t *)calloc(1, sizeof(ipp_t))) != NULL)
+  {
+   /*
+    * Default to IPP 2.0...
+    */
+
+    temp->request.any.version[0] = 2;
+    temp->request.any.version[1] = 0;
+    temp->use                    = 1;
+  }
+
+  DEBUG_printf(("1ippNew: Returning %p", temp));
+
+  return (temp);
+}
+
+
+/*
+ *  'ippNewRequest()' - Allocate a new IPP request message.
+ *
+ * The new request message is initialized with the attributes-charset and
+ * attributes-natural-language attributes added. The
+ * attributes-natural-language value is derived from the current locale.
+ *
+ * @since CUPS 1.2/Mac OS X 10.5@
+ */
+
+ipp_t *                                        /* O - IPP request message */
+ippNewRequest(ipp_op_t op)             /* I - Operation code */
+{
+  ipp_t                *request;               /* IPP request message */
+  cups_lang_t  *language;              /* Current language localization */
+  static int   request_id = 0;         /* Current request ID */
+  static _cups_mutex_t request_mutex = _CUPS_MUTEX_INITIALIZER;
+                                       /* Mutex for request ID */
+
+
+  DEBUG_printf(("ippNewRequest(op=%02x(%s))", op, ippOpString(op)));
+
+ /*
+  * Create a new IPP message...
+  */
+
+  if ((request = ippNew()) == NULL)
+    return (NULL);
+
+ /*
+  * Set the operation and request ID...
+  */
+
+  _cupsMutexLock(&request_mutex);
+
+  request->request.op.operation_id = op;
+  request->request.op.request_id   = ++request_id;
+
+  _cupsMutexUnlock(&request_mutex);
+
+ /*
+  * Use UTF-8 as the character set...
+  */
+
+  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+               "attributes-charset", NULL, "utf-8");
+
+ /*
+  * Get the language from the current locale...
+  */
+
+  language = cupsLangDefault();
+
+  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+               "attributes-natural-language", NULL, language->language);
+
+ /*
+  * Return the new request...
+  */
+
+  return (request);
+}
+
+
+/*
+ * 'ippRead()' - Read data for an IPP message from a HTTP connection.
+ */
+
+ipp_state_t                            /* O - Current state */
+ippRead(http_t *http,                  /* I - HTTP connection */
+        ipp_t  *ipp)                   /* I - IPP data */
+{
+  DEBUG_printf(("ippRead(http=%p, ipp=%p), data_remaining=" CUPS_LLFMT,
+                http, ipp, CUPS_LLCAST (http ? http->data_remaining : -1)));
+
+  if (!http)
+    return (IPP_ERROR);
+
+  DEBUG_printf(("2ippRead: http->state=%d, http->used=%d", http->state,
+                http->used));
+
+  return (ippReadIO(http, (ipp_iocb_t)ipp_read_http, http->blocking, NULL,
+                    ipp));
+}
+
+
+/*
+ * 'ippReadFile()' - Read data for an IPP message from a file.
+ *
+ * @since CUPS 1.1.19/Mac OS X 10.3@
+ */
+
+ipp_state_t                            /* O - Current state */
+ippReadFile(int   fd,                  /* I - HTTP data */
+            ipp_t *ipp)                        /* I - IPP data */
+{
+  DEBUG_printf(("ippReadFile(fd=%d, ipp=%p)", fd, ipp));
+
+  return (ippReadIO(&fd, (ipp_iocb_t)ipp_read_file, 1, NULL, ipp));
+}
+
+
+/*
+ * 'ippReadIO()' - Read data for an IPP message.
+ *
+ * @since CUPS 1.2/Mac OS X 10.5@
+ */
+
+ipp_state_t                            /* O - Current state */
+ippReadIO(void       *src,             /* I - Data source */
+          ipp_iocb_t cb,               /* I - Read callback function */
+         int        blocking,          /* I - Use blocking IO? */
+         ipp_t      *parent,           /* I - Parent request, if any */
+          ipp_t      *ipp)             /* I - IPP data */
+{
+  int                  n;              /* Length of data */
+  unsigned char                *buffer,        /* Data buffer */
+                       string[IPP_MAX_NAME],
+                                       /* Small string buffer */
+                       *bufptr;        /* Pointer into buffer */
+  ipp_attribute_t      *attr;          /* Current attribute */
+  ipp_tag_t            tag;            /* Current tag */
+  ipp_tag_t            value_tag;      /* Current value tag */
+  _ipp_value_t         *value;         /* Current value */
+
+
+  DEBUG_printf(("ippReadIO(src=%p, cb=%p, blocking=%d, parent=%p, ipp=%p)",
+                src, cb, blocking, parent, ipp));
+  DEBUG_printf(("2ippReadIO: ipp->state=%d", ipp->state));
+
+  if (!src || !ipp)
+    return (IPP_ERROR);
+
+  if ((buffer = ipp_buffer_get()) == NULL)
+  {
+    DEBUG_puts("1ippReadIO: Unable to get read buffer.");
+    return (IPP_ERROR);
+  }
+
+  switch (ipp->state)
+  {
+    case IPP_IDLE :
+        ipp->state ++; /* Avoid common problem... */
+
+    case IPP_HEADER :
+        if (parent == NULL)
+       {
+        /*
+          * Get the request header...
+         */
+
+          if ((*cb)(src, buffer, 8) < 8)
+         {
+           DEBUG_puts("1ippReadIO: Unable to read header.");
+           ipp_buffer_release(buffer);
+           return (IPP_ERROR);
+         }
+
+        /*
+          * Then copy the request header over...
+         */
+
+          ipp->request.any.version[0]  = buffer[0];
+          ipp->request.any.version[1]  = buffer[1];
+          ipp->request.any.op_status   = (buffer[2] << 8) | buffer[3];
+          ipp->request.any.request_id  = (((((buffer[4] << 8) | buffer[5]) << 8) |
+                                        buffer[6]) << 8) | buffer[7];
+
+          DEBUG_printf(("2ippReadIO: version=%d.%d", buffer[0], buffer[1]));
+         DEBUG_printf(("2ippReadIO: op_status=%04x",
+                       ipp->request.any.op_status));
+         DEBUG_printf(("2ippReadIO: request_id=%d",
+                       ipp->request.any.request_id));
+        }
+
+        ipp->state   = IPP_ATTRIBUTE;
+       ipp->current = NULL;
+       ipp->curtag  = IPP_TAG_ZERO;
+       ipp->prev    = ipp->last;
+
+       /*
+        * If blocking is disabled, stop here...
+       */
+
+        if (!blocking)
+         break;
+
+    case IPP_ATTRIBUTE :
+        for (;;)
+       {
+         if ((*cb)(src, buffer, 1) < 1)
+         {
+           DEBUG_puts("1ippReadIO: Callback returned EOF/error");
+           ipp_buffer_release(buffer);
+           return (IPP_ERROR);
+         }
+
+         DEBUG_printf(("2ippReadIO: ipp->current=%p, ipp->prev=%p",
+                       ipp->current, ipp->prev));
+
+        /*
+         * Read this attribute...
+         */
+
+          tag = (ipp_tag_t)buffer[0];
+          if (tag == IPP_TAG_EXTENSION)
+          {
+           /*
+            * Read 32-bit "extension" tag...
+            */
+
+           if ((*cb)(src, buffer, 4) < 1)
+           {
+             DEBUG_puts("1ippReadIO: Callback returned EOF/error");
+             ipp_buffer_release(buffer);
+             return (IPP_ERROR);
+           }
+
+           tag = (ipp_tag_t)((((((buffer[0] << 8) | buffer[1]) << 8) |
+                               buffer[2]) << 8) | buffer[3]);
+
+            if (tag & IPP_TAG_COPY)
+            {
+             /*
+              * Fail if the high bit is set in the tag...
+              */
+
+             _cupsSetError(IPP_ERROR, _("IPP extension tag larger than 0x7FFFFFFF."), 1);
+             DEBUG_printf(("1ippReadIO: bad name length %d.", n));
+             ipp_buffer_release(buffer);
+             return (IPP_ERROR);
+            }
+          }
+
+         if (tag == IPP_TAG_END)
+         {
+          /*
+           * No more attributes left...
+           */
+
+            DEBUG_puts("2ippReadIO: IPP_TAG_END.");
+
+           ipp->state = IPP_DATA;
+           break;
+         }
+          else if (tag < IPP_TAG_UNSUPPORTED_VALUE)
+         {
+          /*
+           * Group tag...  Set the current group and continue...
+           */
+
+            if (ipp->curtag == tag)
+             ipp->prev = ippAddSeparator(ipp);
+            else if (ipp->current)
+             ipp->prev = ipp->current;
 
            ipp->curtag  = tag;
            ipp->current = NULL;
@@ -1216,617 +2453,1242 @@ ippReadIO(void       *src,           /* I - Data source */
            continue;
          }
 
-          DEBUG_printf(("2ippReadIO: value tag=%x(%s)", tag,
-                       ippTagString(tag)));
+          DEBUG_printf(("2ippReadIO: value tag=%x(%s)", tag,
+                       ippTagString(tag)));
+
+         /*
+         * Get the name...
+         */
+
+          if ((*cb)(src, buffer, 2) < 2)
+         {
+           DEBUG_puts("1ippReadIO: unable to read name length.");
+           ipp_buffer_release(buffer);
+           return (IPP_ERROR);
+         }
+
+          n = (buffer[0] << 8) | buffer[1];
+
+          if (n >= IPP_BUF_SIZE)
+         {
+           _cupsSetError(IPP_ERROR, _("IPP name larger than 32767 bytes."), 1);
+           DEBUG_printf(("1ippReadIO: bad name length %d.", n));
+           ipp_buffer_release(buffer);
+           return (IPP_ERROR);
+         }
+
+          DEBUG_printf(("2ippReadIO: name length=%d", n));
+
+          if (n == 0 && tag != IPP_TAG_MEMBERNAME &&
+             tag != IPP_TAG_END_COLLECTION)
+         {
+          /*
+           * More values for current attribute...
+           */
+
+            if (ipp->current == NULL)
+           {
+             _cupsSetError(IPP_ERROR, _("IPP attribute has no name."), 1);
+             DEBUG_puts("1ippReadIO: Attribute without name and no current.");
+             ipp_buffer_release(buffer);
+             return (IPP_ERROR);
+           }
+
+            attr      = ipp->current;
+           value_tag = (ipp_tag_t)(attr->value_tag & IPP_TAG_MASK);
+
+          /*
+           * Make sure we aren't adding a new value of a different
+           * type...
+           */
+
+           if (value_tag == IPP_TAG_ZERO)
+           {
+            /*
+             * Setting the value of a collection member...
+             */
+
+             attr->value_tag = tag;
+           }
+           else if (value_tag == IPP_TAG_TEXTLANG ||
+                    value_tag == IPP_TAG_NAMELANG ||
+                    (value_tag >= IPP_TAG_TEXT &&
+                     value_tag <= IPP_TAG_MIMETYPE))
+            {
+            /*
+             * String values can sometimes come across in different
+             * forms; accept sets of differing values...
+             */
+
+             if (tag != IPP_TAG_TEXTLANG && tag != IPP_TAG_NAMELANG &&
+                 (tag < IPP_TAG_TEXT || tag > IPP_TAG_MIMETYPE) &&
+                 tag != IPP_TAG_NOVALUE)
+             {
+               _cupsSetError(IPP_ERROR,
+                             _("IPP 1setOf attribute with incompatible value "
+                               "tags."), 1);
+               DEBUG_printf(("1ippReadIO: 1setOf value tag %x(%s) != %x(%s)",
+                             value_tag, ippTagString(value_tag), tag,
+                             ippTagString(tag)));
+               ipp_buffer_release(buffer);
+               return (IPP_ERROR);
+             }
+
+              if (value_tag != tag)
+              {
+                DEBUG_printf(("1ippReadIO: Converting %s attribute from %s to %s.",
+                              attr->name, ippTagString(value_tag), ippTagString(tag)));
+               ippSetValueTag(ipp, &attr, tag);
+             }
+            }
+           else if (value_tag == IPP_TAG_INTEGER ||
+                    value_tag == IPP_TAG_RANGE)
+            {
+            /*
+             * Integer and rangeOfInteger values can sometimes be mixed; accept
+             * sets of differing values...
+             */
+
+             if (tag != IPP_TAG_INTEGER && tag != IPP_TAG_RANGE)
+             {
+               _cupsSetError(IPP_ERROR,
+                             _("IPP 1setOf attribute with incompatible value "
+                               "tags."), 1);
+               DEBUG_printf(("1ippReadIO: 1setOf value tag %x(%s) != %x(%s)",
+                             value_tag, ippTagString(value_tag), tag,
+                             ippTagString(tag)));
+               ipp_buffer_release(buffer);
+               return (IPP_ERROR);
+             }
+
+              if (value_tag == IPP_TAG_INTEGER && tag == IPP_TAG_RANGE)
+              {
+               /*
+                * Convert integer values to rangeOfInteger values...
+                */
+
+               DEBUG_printf(("1ippReadIO: Converting %s attribute to "
+                             "rangeOfInteger.", attr->name));
+                ippSetValueTag(ipp, &attr, IPP_TAG_RANGE);
+              }
+            }
+           else if (value_tag != tag)
+           {
+             _cupsSetError(IPP_ERROR,
+                           _("IPP 1setOf attribute with incompatible value "
+                             "tags."), 1);
+             DEBUG_printf(("1ippReadIO: value tag %x(%s) != %x(%s)",
+                           value_tag, ippTagString(value_tag), tag,
+                           ippTagString(tag)));
+             ipp_buffer_release(buffer);
+             return (IPP_ERROR);
+            }
+
+           /*
+           * Finally, reallocate the attribute array as needed...
+           */
+
+           if ((value = ipp_set_value(ipp, &attr, attr->num_values)) == NULL)
+           {
+             ipp_buffer_release(buffer);
+             return (IPP_ERROR);
+           }
+         }
+         else if (tag == IPP_TAG_MEMBERNAME)
+         {
+          /*
+           * Name must be length 0!
+           */
+
+           if (n)
+           {
+             _cupsSetError(IPP_ERROR, _("IPP member name is not empty."), 1);
+             DEBUG_puts("1ippReadIO: member name not empty.");
+             ipp_buffer_release(buffer);
+             return (IPP_ERROR);
+           }
+
+            if (ipp->current)
+             ipp->prev = ipp->current;
+
+           attr = ipp->current = ipp_add_attr(ipp, NULL, ipp->curtag, IPP_TAG_ZERO, 1);
+
+           DEBUG_printf(("2ippReadIO: membername, ipp->current=%p, ipp->prev=%p",
+                         ipp->current, ipp->prev));
+
+           attr->num_values = 0;
+           value            = attr->values;
+         }
+         else if (tag != IPP_TAG_END_COLLECTION)
+         {
+          /*
+           * New attribute; read the name and add it...
+           */
+
+           if ((*cb)(src, buffer, n) < n)
+           {
+             DEBUG_puts("1ippReadIO: unable to read name.");
+             ipp_buffer_release(buffer);
+             return (IPP_ERROR);
+           }
+
+           buffer[n] = '\0';
+
+            if (ipp->current)
+             ipp->prev = ipp->current;
+
+           if ((attr = ipp->current = ipp_add_attr(ipp, (char *)buffer, ipp->curtag, tag,
+                                                   1)) == NULL)
+           {
+             _cupsSetHTTPError(HTTP_ERROR);
+             DEBUG_puts("1ippReadIO: unable to allocate attribute.");
+             ipp_buffer_release(buffer);
+             return (IPP_ERROR);
+           }
+
+           DEBUG_printf(("2ippReadIO: name=\"%s\", ipp->current=%p, "
+                         "ipp->prev=%p", buffer, ipp->current, ipp->prev));
+
+           attr->num_values = 0;
+           value            = attr->values;
+         }
+         else
+         {
+           attr  = NULL;
+           value = NULL;
+         }
+
+         if ((*cb)(src, buffer, 2) < 2)
+         {
+           DEBUG_puts("1ippReadIO: unable to read value length.");
+           ipp_buffer_release(buffer);
+           return (IPP_ERROR);
+         }
+
+         n = (buffer[0] << 8) | buffer[1];
+          DEBUG_printf(("2ippReadIO: value length=%d", n));
+
+         if (n >= IPP_BUF_SIZE)
+         {
+           _cupsSetError(IPP_ERROR,
+                         _("IPP value larger than 32767 bytes."), 1);
+           DEBUG_printf(("1ippReadIO: bad value length %d.", n));
+           ipp_buffer_release(buffer);
+           return (IPP_ERROR);
+         }
+
+         switch (tag)
+         {
+           case IPP_TAG_INTEGER :
+           case IPP_TAG_ENUM :
+               if (n != 4)
+               {
+                 if (tag == IPP_TAG_INTEGER)
+                   _cupsSetError(IPP_ERROR,
+                                 _("IPP integer value not 4 bytes."), 1);
+                 else
+                   _cupsSetError(IPP_ERROR,
+                                 _("IPP enum value not 4 bytes."), 1);
+                 DEBUG_printf(("1ippReadIO: bad value length %d.", n));
+                 ipp_buffer_release(buffer);
+                 return (IPP_ERROR);
+               }
+
+               if ((*cb)(src, buffer, 4) < 4)
+               {
+                 DEBUG_puts("1ippReadIO: Unable to read integer value.");
+                 ipp_buffer_release(buffer);
+                 return (IPP_ERROR);
+               }
+
+               n = (((((buffer[0] << 8) | buffer[1]) << 8) | buffer[2]) << 8) |
+                   buffer[3];
+
+                if (attr->value_tag == IPP_TAG_RANGE)
+                  value->range.lower = value->range.upper = n;
+                else
+                 value->integer = n;
+               break;
+
+           case IPP_TAG_BOOLEAN :
+               if (n != 1)
+               {
+                 _cupsSetError(IPP_ERROR, _("IPP boolean value not 1 byte."),
+                               1);
+                 DEBUG_printf(("1ippReadIO: bad value length %d.", n));
+                 ipp_buffer_release(buffer);
+                 return (IPP_ERROR);
+               }
+
+               if ((*cb)(src, buffer, 1) < 1)
+               {
+                 DEBUG_puts("1ippReadIO: Unable to read boolean value.");
+                 ipp_buffer_release(buffer);
+                 return (IPP_ERROR);
+               }
+
+                value->boolean = buffer[0];
+               break;
+
+            case IPP_TAG_NOVALUE :
+           case IPP_TAG_NOTSETTABLE :
+           case IPP_TAG_DELETEATTR :
+           case IPP_TAG_ADMINDEFINE :
+              /*
+               * These value types are not supposed to have values, however
+               * some vendors (Brother) do not implement IPP correctly and so
+               * we need to map non-empty values to text...
+               */
+
+               if (attr->value_tag == tag)
+               {
+                 if (n == 0)
+                   break;
+
+                 attr->value_tag = IPP_TAG_TEXT;
+               }
+
+           case IPP_TAG_TEXT :
+           case IPP_TAG_NAME :
+           case IPP_TAG_KEYWORD :
+           case IPP_TAG_URI :
+           case IPP_TAG_URISCHEME :
+           case IPP_TAG_CHARSET :
+           case IPP_TAG_LANGUAGE :
+           case IPP_TAG_MIMETYPE :
+               if ((*cb)(src, buffer, n) < n)
+               {
+                 DEBUG_puts("1ippReadIO: unable to read string value.");
+                 ipp_buffer_release(buffer);
+                 return (IPP_ERROR);
+               }
+
+               buffer[n] = '\0';
+               value->string.text = _cupsStrAlloc((char *)buffer);
+               DEBUG_printf(("2ippReadIO: value=\"%s\"", value->string.text));
+               break;
+
+           case IPP_TAG_DATE :
+               if (n != 11)
+               {
+                 _cupsSetError(IPP_ERROR, _("IPP date value not 11 bytes."), 1);
+                 DEBUG_printf(("1ippReadIO: bad value length %d.", n));
+                 ipp_buffer_release(buffer);
+                 return (IPP_ERROR);
+               }
+
+               if ((*cb)(src, value->date, 11) < 11)
+               {
+                 DEBUG_puts("1ippReadIO: Unable to read date value.");
+                 ipp_buffer_release(buffer);
+                 return (IPP_ERROR);
+               }
+               break;
+
+           case IPP_TAG_RESOLUTION :
+               if (n != 9)
+               {
+                 _cupsSetError(IPP_ERROR,
+                               _("IPP resolution value not 9 bytes."), 1);
+                 DEBUG_printf(("1ippReadIO: bad value length %d.", n));
+                 ipp_buffer_release(buffer);
+                 return (IPP_ERROR);
+               }
+
+               if ((*cb)(src, buffer, 9) < 9)
+               {
+                 DEBUG_puts("1ippReadIO: Unable to read resolution value.");
+                 ipp_buffer_release(buffer);
+                 return (IPP_ERROR);
+               }
+
+                value->resolution.xres =
+                   (((((buffer[0] << 8) | buffer[1]) << 8) | buffer[2]) << 8) |
+                   buffer[3];
+                value->resolution.yres =
+                   (((((buffer[4] << 8) | buffer[5]) << 8) | buffer[6]) << 8) |
+                   buffer[7];
+                value->resolution.units =
+                   (ipp_res_t)buffer[8];
+               break;
+
+           case IPP_TAG_RANGE :
+               if (n != 8)
+               {
+                 _cupsSetError(IPP_ERROR,
+                               _("IPP rangeOfInteger value not 8 bytes."), 1);
+                 DEBUG_printf(("1ippReadIO: bad value length %d.", n));
+                 ipp_buffer_release(buffer);
+                 return (IPP_ERROR);
+               }
+
+               if ((*cb)(src, buffer, 8) < 8)
+               {
+                 DEBUG_puts("1ippReadIO: Unable to read range value.");
+                 ipp_buffer_release(buffer);
+                 return (IPP_ERROR);
+               }
+
+                value->range.lower =
+                   (((((buffer[0] << 8) | buffer[1]) << 8) | buffer[2]) << 8) |
+                   buffer[3];
+                value->range.upper =
+                   (((((buffer[4] << 8) | buffer[5]) << 8) | buffer[6]) << 8) |
+                   buffer[7];
+               break;
+
+           case IPP_TAG_TEXTLANG :
+           case IPP_TAG_NAMELANG :
+               if (n < 4)
+               {
+                 if (tag == IPP_TAG_TEXTLANG)
+                   _cupsSetError(IPP_ERROR,
+                                 _("IPP textWithLanguage value less than "
+                                   "minimum 4 bytes."), 1);
+                 else
+                   _cupsSetError(IPP_ERROR,
+                                 _("IPP nameWithLanguage value less than "
+                                   "minimum 4 bytes."), 1);
+                 DEBUG_printf(("1ippReadIO: bad value length %d.", n));
+                 ipp_buffer_release(buffer);
+                 return (IPP_ERROR);
+               }
+
+               if ((*cb)(src, buffer, n) < n)
+               {
+                 DEBUG_puts("1ippReadIO: Unable to read string w/language "
+                            "value.");
+                 ipp_buffer_release(buffer);
+                 return (IPP_ERROR);
+               }
+
+                bufptr = buffer;
+
+              /*
+               * text-with-language and name-with-language are composite
+               * values:
+               *
+               *    language-length
+               *    language
+               *    text-length
+               *    text
+               */
+
+               n = (bufptr[0] << 8) | bufptr[1];
+
+               if ((bufptr + 2 + n) >= (buffer + IPP_BUF_SIZE) ||
+                   n >= sizeof(string))
+               {
+                 _cupsSetError(IPP_ERROR,
+                               _("IPP language length overflows value."), 1);
+                 DEBUG_printf(("1ippReadIO: bad value length %d.", n));
+                 ipp_buffer_release(buffer);
+                 return (IPP_ERROR);
+               }
+
+               memcpy(string, bufptr + 2, n);
+               string[n] = '\0';
+
+               value->string.language = _cupsStrAlloc((char *)string);
+
+                bufptr += 2 + n;
+               n = (bufptr[0] << 8) | bufptr[1];
+
+               if ((bufptr + 2 + n) >= (buffer + IPP_BUF_SIZE))
+               {
+                 _cupsSetError(IPP_ERROR,
+                               _("IPP string length overflows value."), 1);
+                 DEBUG_printf(("1ippReadIO: bad value length %d.", n));
+                 ipp_buffer_release(buffer);
+                 return (IPP_ERROR);
+               }
+
+               bufptr[2 + n] = '\0';
+                value->string.text = _cupsStrAlloc((char *)bufptr + 2);
+               break;
+
+            case IPP_TAG_BEGIN_COLLECTION :
+              /*
+               * Oh, boy, here comes a collection value, so read it...
+               */
+
+                value->collection = ippNew();
+
+                if (n > 0)
+               {
+                 _cupsSetError(IPP_ERROR,
+                               _("IPP begCollection value not 0 bytes."), 1);
+                 DEBUG_puts("1ippReadIO: begCollection tag with value length "
+                            "> 0.");
+                 ipp_buffer_release(buffer);
+                 return (IPP_ERROR);
+               }
+
+               if (ippReadIO(src, cb, 1, ipp, value->collection) == IPP_ERROR)
+               {
+                 DEBUG_puts("1ippReadIO: Unable to read collection value.");
+                 ipp_buffer_release(buffer);
+                 return (IPP_ERROR);
+               }
+                break;
+
+            case IPP_TAG_END_COLLECTION :
+               ipp_buffer_release(buffer);
+
+                if (n > 0)
+               {
+                 _cupsSetError(IPP_ERROR,
+                               _("IPP endCollection value not 0 bytes."), 1);
+                 DEBUG_puts("1ippReadIO: endCollection tag with value length "
+                            "> 0.");
+                 return (IPP_ERROR);
+               }
+
+               DEBUG_puts("1ippReadIO: endCollection tag...");
+               return (ipp->state = IPP_DATA);
+
+            case IPP_TAG_MEMBERNAME :
+              /*
+               * The value the name of the member in the collection, which
+               * we need to carry over...
+               */
+
+               if ((*cb)(src, buffer, n) < n)
+               {
+                 DEBUG_puts("1ippReadIO: Unable to read member name value.");
+                 ipp_buffer_release(buffer);
+                 return (IPP_ERROR);
+               }
+
+               buffer[n] = '\0';
+               attr->name = _cupsStrAlloc((char *)buffer);
+
+               /*
+               * Since collection members are encoded differently than
+               * regular attributes, make sure we don't start with an
+               * empty value...
+               */
+
+                attr->num_values --;
+
+               DEBUG_printf(("2ippReadIO: member name=\"%s\"", attr->name));
+               break;
+
+            default : /* Other unsupported values */
+                value->unknown.length = n;
+               if (n > 0)
+               {
+                 if ((value->unknown.data = malloc(n)) == NULL)
+                 {
+                   _cupsSetHTTPError(HTTP_ERROR);
+                   DEBUG_puts("1ippReadIO: Unable to allocate value");
+                   ipp_buffer_release(buffer);
+                   return (IPP_ERROR);
+                 }
+
+                 if ((*cb)(src, value->unknown.data, n) < n)
+                 {
+                   DEBUG_puts("1ippReadIO: Unable to read unsupported value.");
+                   ipp_buffer_release(buffer);
+                   return (IPP_ERROR);
+                 }
+               }
+               else
+                 value->unknown.data = NULL;
+               break;
+         }
+
+          attr->num_values ++;
 
-         /*
-         * Get the name...
+        /*
+          * If blocking is disabled, stop here...
          */
 
-          if ((*cb)(src, buffer, 2) < 2)
-         {
-           DEBUG_puts("1ippReadIO: unable to read name length.");
-           ipp_buffer_release(buffer);
-           return (IPP_ERROR);
-         }
+          if (!blocking)
+           break;
+       }
+        break;
 
-          n = (buffer[0] << 8) | buffer[1];
+    case IPP_DATA :
+        break;
 
-          if (n >= IPP_BUF_SIZE)
-         {
-           _cupsSetError(IPP_ERROR, _("IPP name larger than 32767 bytes."), 1);
-           DEBUG_printf(("1ippReadIO: bad name length %d.", n));
-           ipp_buffer_release(buffer);
-           return (IPP_ERROR);
-         }
+    default :
+        break; /* anti-compiler-warning-code */
+  }
 
-          DEBUG_printf(("2ippReadIO: name length=%d", n));
+  DEBUG_printf(("1ippReadIO: returning ipp->state=%d.", ipp->state));
+  ipp_buffer_release(buffer);
 
-          if (n == 0 && tag != IPP_TAG_MEMBERNAME &&
-             tag != IPP_TAG_END_COLLECTION)
-         {
-          /*
-           * More values for current attribute...
-           */
+  return (ipp->state);
+}
 
-            if (ipp->current == NULL)
-           {
-             _cupsSetError(IPP_ERROR, _("IPP attribute has no name."), 1);
-             DEBUG_puts("1ippReadIO: Attribute without name and no current.");
-             ipp_buffer_release(buffer);
-             return (IPP_ERROR);
-           }
 
-            attr      = ipp->current;
-           value_tag = (ipp_tag_t)(attr->value_tag & IPP_TAG_MASK);
+/*
+ * 'ippSetBoolean()' - Set a boolean value in an attribute.
+ *
+ * The @code ipp@ parameter refers to the IPP message containing the attribute that was
+ * previously created using the @link ippNew@ or @link ippNewRequest@ functions.
+ *
+ * The @code attr@ parameter may be modified as a result of setting the value.
+ *
+ * The @code element@ parameter specifies which value to set from 0 to
+ * @link ippGetCount(attr)@.
+ *
+ * @since CUPS 1.6@
+ */
 
-          /*
-           * Make sure we aren't adding a new value of a different
-           * type...
-           */
+int                                    /* O  - 1 on success, 0 on failure */
+ippSetBoolean(ipp_t           *ipp,    /* I  - IPP message */
+              ipp_attribute_t **attr,  /* IO - IPP attribute */
+              int             element, /* I  - Value number (0-based) */
+              int             boolvalue)/* I  - Boolean value */
+{
+  _ipp_value_t *value;                 /* Current value */
 
-           if (value_tag == IPP_TAG_ZERO)
-           {
-            /*
-             * Setting the value of a collection member...
-             */
 
-             attr->value_tag = tag;
-           }
-           else if (value_tag == IPP_TAG_TEXTLANG ||
-                    value_tag == IPP_TAG_NAMELANG ||
-                    (value_tag >= IPP_TAG_TEXT &&
-                     value_tag <= IPP_TAG_MIMETYPE))
-            {
-            /*
-             * String values can sometimes come across in different
-             * forms; accept sets of differing values...
-             */
+ /*
+  * Range check input...
+  */
 
-             if (tag != IPP_TAG_TEXTLANG && tag != IPP_TAG_NAMELANG &&
-                 (tag < IPP_TAG_TEXT || tag > IPP_TAG_MIMETYPE) &&
-                 tag != IPP_TAG_NOVALUE)
-             {
-               _cupsSetError(IPP_ERROR,
-                             _("IPP 1setOf attribute with incompatible value "
-                               "tags."), 1);
-               DEBUG_printf(("1ippReadIO: 1setOf value tag %x(%s) != %x(%s)",
-                             value_tag, ippTagString(value_tag), tag,
-                             ippTagString(tag)));
-               ipp_buffer_release(buffer);
-               return (IPP_ERROR);
-             }
-            }
-           else if (value_tag == IPP_TAG_INTEGER ||
-                    value_tag == IPP_TAG_RANGE)
-            {
-            /*
-             * Integer and rangeOfInteger values can sometimes be mixed; accept
-             * sets of differing values...
-             */
+  if (!ipp || !attr || !*attr || (*attr)->value_tag != IPP_TAG_BOOLEAN ||
+      element < 0 || element > (*attr)->num_values)
+    return (0);
 
-             if (tag != IPP_TAG_INTEGER && tag != IPP_TAG_RANGE)
-             {
-               _cupsSetError(IPP_ERROR,
-                             _("IPP 1setOf attribute with incompatible value "
-                               "tags."), 1);
-               DEBUG_printf(("1ippReadIO: 1setOf value tag %x(%s) != %x(%s)",
-                             value_tag, ippTagString(value_tag), tag,
-                             ippTagString(tag)));
-               ipp_buffer_release(buffer);
-               return (IPP_ERROR);
-             }
+ /*
+  * Set the value and return...
+  */
 
-              if (value_tag == IPP_TAG_INTEGER && tag == IPP_TAG_RANGE)
-              {
-               /*
-                * Convert integer values to rangeOfInteger values...
-                */
+  if ((value = ipp_set_value(ipp, attr, element)) != NULL)
+    value->boolean = boolvalue;
 
-               int i;                  /* Looping var */
+  return (value != NULL);
+}
 
-               DEBUG_printf(("1ippReadIO: Converting %s attribute to "
-                             "rangeOfInteger.", attr->name));
 
-               attr->value_tag = IPP_TAG_RANGE;
+/*
+ * 'ippSetCollection()' - Set a collection value in an attribute.
+ *
+ * The @code ipp@ parameter refers to the IPP message containing the attribute that was
+ * previously created using the @link ippNew@ or @link ippNewRequest@ functions.
+ *
+ * The @code attr@ parameter may be modified as a result of setting the value.
+ *
+ * The @code element@ parameter specifies which value to set from 0 to
+ * @link ippGetCount(attr)@.
+ *
+ * @since CUPS 1.6@
+ */
 
-                for (i = attr->num_values, value = attr->values;
-                     i > 0;
-                     i --, value ++)
-                {
-                  n                  = value->integer;
-                  value->range.lower = value->range.upper = n;
-                }
-              }
-            }
-           else if (value_tag != tag)
-           {
-             _cupsSetError(IPP_ERROR,
-                           _("IPP 1setOf attribute with incompatible value "
-                             "tags."), 1);
-             DEBUG_printf(("1ippReadIO: value tag %x(%s) != %x(%s)",
-                           value_tag, ippTagString(value_tag), tag,
-                           ippTagString(tag)));
-             ipp_buffer_release(buffer);
-             return (IPP_ERROR);
-            }
+int                                    /* O  - 1 on success, 0 on failure */
+ippSetCollection(
+    ipp_t           *ipp,              /* I  - IPP message */
+    ipp_attribute_t **attr,            /* IO - IPP attribute */
+    int             element,           /* I  - Value number (0-based) */
+    ipp_t           *colvalue)         /* I  - Collection value */
+{
+  _ipp_value_t *value;                 /* Current value */
+
+
+ /*
+  * Range check input...
+  */
+
+  if (!ipp || !attr || !*attr || (*attr)->value_tag != IPP_TAG_BEGIN_COLLECTION ||
+      element < 0 || element > (*attr)->num_values || !colvalue)
+    return (0);
+
+ /*
+  * Set the value and return...
+  */
+
+  if ((value = ipp_set_value(ipp, attr, element)) != NULL)
+  {
+    if (value->collection)
+      ippDelete(value->collection);
+
+    value->collection = colvalue;
+    colvalue->use ++;
+  }
+
+  return (value != NULL);
+}
+
+
+/*
+ * 'ippSetGroupTag()' - Set the group tag of an attribute.
+ *
+ * The @code ipp@ parameter refers to the IPP message containing the attribute that was
+ * previously created using the @link ippNew@ or @link ippNewRequest@ functions.
+ *
+ * The @code attr@ parameter may be modified as a result of setting the value.
+ *
+ * The @code group@ parameter specifies the IPP attribute group tag: none
+ * (@code IPP_TAG_ZERO@, for member attributes), document (@code IPP_TAG_DOCUMENT@),
+ * event notification (@code IPP_TAG_EVENT_NOTIFICATION@), operation
+ * (@code IPP_TAG_OPERATION@), printer (@code IPP_TAG_PRINTER@), subscription
+ * (@code IPP_TAG_SUBSCRIPTION@), or unsupported (@code IPP_TAG_UNSUPPORTED_GROUP@).
+ *
+ * @since CUPS 1.6@
+ */
+
+int                                    /* O  - 1 on success, 0 on failure */
+ippSetGroupTag(
+    ipp_t           *ipp,              /* I  - IPP message */
+    ipp_attribute_t **attr,            /* IO - Attribute */
+    ipp_tag_t       group_tag)         /* I  - Group tag */
+{
+ /*
+  * Range check input - group tag must be 0x01 to 0x0F, per RFC 2911...
+  */
+
+  if (!ipp || !attr || group_tag < IPP_TAG_ZERO || group_tag == IPP_TAG_END ||
+      group_tag >= IPP_TAG_UNSUPPORTED_VALUE)
+    return (0);
+
+ /*
+  * Set the group tag and return...
+  */
+
+  (*attr)->group_tag = group_tag;
+
+  return (1);
+}
+
+
+/*
+ * 'ippSetInteger()' - Set an integer or enum value in an attribute.
+ *
+ * The @code ipp@ parameter refers to the IPP message containing the attribute that was
+ * previously created using the @link ippNew@ or @link ippNewRequest@ functions.
+ *
+ * The @code attr@ parameter may be modified as a result of setting the value.
+ *
+ * The @code element@ parameter specifies which value to set from 0 to
+ * @link ippGetCount(attr)@.
+ *
+ * @since CUPS 1.6@
+ */
+
+int                                    /* O  - 1 on success, 0 on failure */
+ippSetInteger(ipp_t           *ipp,    /* I  - IPP message */
+              ipp_attribute_t **attr,  /* IO - IPP attribute */
+              int             element, /* I  - Value number (0-based) */
+              int             intvalue)        /* I  - Integer/enum value */
+{
+  _ipp_value_t *value;                 /* Current value */
+
+
+ /*
+  * Range check input...
+  */
+
+  if (!ipp || !attr || !*attr ||
+      ((*attr)->value_tag != IPP_TAG_INTEGER && (*attr)->value_tag != IPP_TAG_ENUM) ||
+      element < 0 || element > (*attr)->num_values)
+    return (0);
+
+ /*
+  * Set the value and return...
+  */
+
+  if ((value = ipp_set_value(ipp, attr, element)) != NULL)
+    value->integer = intvalue;
+
+  return (value != NULL);
+}
+
+
+/*
+ * 'ippSetName()' - Set the name of an attribute.
+ *
+ * The @code ipp@ parameter refers to the IPP message containing the attribute that was
+ * previously created using the @link ippNew@ or @link ippNewRequest@ functions.
+ *
+ * The @code attr@ parameter may be modified as a result of setting the value.
+ *
+ * @since CUPS 1.6@
+ */
+
+int                                    /* O  - 1 on success, 0 on failure */
+ippSetName(ipp_t           *ipp,       /* I  - IPP message */
+          ipp_attribute_t **attr,      /* IO - IPP attribute */
+          const char      *name)       /* I  - Attribute name */
+{
+  char *temp;                          /* Temporary name value */
+
+
+ /*
+  * Range check input...
+  */
+
+  if (!ipp || !attr || !*attr)
+    return (0);
 
          /*
-           * Finally, reallocate the attribute array as needed...
-           */
+ /*
+  * Set the value and return...
+  */
 
-           if (attr->num_values == 1 ||
-               (attr->num_values > 0 &&
-                (attr->num_values & (IPP_MAX_VALUES - 1)) == 0))
-           {
-             ipp_attribute_t   *temp;  /* Pointer to new buffer */
+  if ((temp = _cupsStrAlloc(name)) != NULL)
+  {
+    if ((*attr)->name)
+      _cupsStrFree((*attr)->name);
 
-              DEBUG_printf(("2ippReadIO: reallocating for up to %d values...",
-                           attr->num_values + IPP_MAX_VALUES));
+    (*attr)->name = temp;
+  }
 
-             /*
-             * Reallocate memory...
-             */
+  return (temp != NULL);
+}
 
-              if ((temp = realloc(attr, sizeof(ipp_attribute_t) +
-                                       (attr->num_values + IPP_MAX_VALUES - 1) *
-                                       sizeof(ipp_value_t))) == NULL)
-             {
-               _cupsSetHTTPError(HTTP_ERROR);
-               DEBUG_puts("1ippReadIO: Unable to resize attribute");
-               ipp_buffer_release(buffer);
-               return (IPP_ERROR);
-             }
 
-              if (temp != attr)
-             {
-               /*
-               * Reset pointers in the list...
-               */
+/*
+ * 'ippSetOperation()' - Set the operation ID in an IPP request message.
+ *
+ * The @code ipp@ parameter refers to an IPP message previously created using the
+ * @link ippNew@ or @link ippNewRequest@ functions.
+ *
+ * @since CUPS 1.6@
+ */
 
-               if (ipp->prev)
-                 ipp->prev->next = temp;
-               else
-                 ipp->attrs = temp;
+int                                    /* O - 1 on success, 0 on failure */
+ippSetOperation(ipp_t    *ipp,         /* I - IPP request message */
+                ipp_op_t op)           /* I - Operation ID */
+{
+ /*
+  * Range check input...
+  */
 
-               attr = ipp->current = ipp->last = temp;
-             }
-           }
-         }
-         else if (tag == IPP_TAG_MEMBERNAME)
-         {
-          /*
-           * Name must be length 0!
-           */
+  if (!ipp)
+    return (0);
 
-           if (n)
-           {
-             _cupsSetError(IPP_ERROR, _("IPP member name is not empty."), 1);
-             DEBUG_puts("1ippReadIO: member name not empty.");
-             ipp_buffer_release(buffer);
-             return (IPP_ERROR);
-           }
+ /*
+  * Set the operation and return...
+  */
 
-            if (ipp->current)
-             ipp->prev = ipp->current;
+  ipp->request.op.operation_id = op;
 
-           attr = ipp->current = _ippAddAttr(ipp, 1);
+  return (1);
+}
 
-           DEBUG_printf(("2ippReadIO: membername, ipp->current=%p, "
-                         "ipp->prev=%p", ipp->current, ipp->prev));
 
-           attr->group_tag  = ipp->curtag;
-           attr->value_tag  = IPP_TAG_ZERO;
-           attr->num_values = 0;
-         }
-         else if (tag != IPP_TAG_END_COLLECTION)
-         {
-          /*
-           * New attribute; read the name and add it...
-           */
+/*
+ * 'ippSetRange()' - Set a rangeOfInteger value in an attribute.
+ *
+ * The @code ipp@ parameter refers to the IPP message containing the attribute that was
+ * previously created using the @link ippNew@ or @link ippNewRequest@ functions.
+ *
+ * The @code attr@ parameter may be modified as a result of setting the value.
+ *
+ * The @code element@ parameter specifies which value to set from 0 to
+ * @link ippGetCount(attr)@.
+ *
+ * @since CUPS 1.6@
+ */
 
-           if ((*cb)(src, buffer, n) < n)
-           {
-             DEBUG_puts("1ippReadIO: unable to read name.");
-             ipp_buffer_release(buffer);
-             return (IPP_ERROR);
-           }
+int                                    /* O  - 1 on success, 0 on failure */
+ippSetRange(ipp_t           *ipp,      /* I  - IPP message */
+            ipp_attribute_t **attr,    /* IO - IPP attribute */
+            int             element,   /* I  - Value number (0-based) */
+           int             lowervalue, /* I  - Lower bound for range */
+           int             uppervalue) /* I  - Upper bound for range */
+{
+  _ipp_value_t *value;                 /* Current value */
 
-           buffer[n] = '\0';
 
-            if (ipp->current)
-             ipp->prev = ipp->current;
+ /*
+  * Range check input...
+  */
 
-           if ((attr = ipp->current = _ippAddAttr(ipp, 1)) == NULL)
-           {
-             _cupsSetHTTPError(HTTP_ERROR);
-             DEBUG_puts("1ippReadIO: unable to allocate attribute.");
-             ipp_buffer_release(buffer);
-             return (IPP_ERROR);
-           }
+  if (!ipp || !attr || !*attr || (*attr)->value_tag != IPP_TAG_RANGE ||
+      element < 0 || element > (*attr)->num_values || lowervalue > uppervalue)
+    return (0);
 
-           DEBUG_printf(("2ippReadIO: name=\"%s\", ipp->current=%p, "
-                         "ipp->prev=%p", buffer, ipp->current, ipp->prev));
+ /*
+  * Set the value and return...
+  */
 
-           attr->group_tag  = ipp->curtag;
-           attr->value_tag  = tag;
-           attr->name       = _cupsStrAlloc((char *)buffer);
-           attr->num_values = 0;
-         }
-         else
-           attr = NULL;
+  if ((value = ipp_set_value(ipp, attr, element)) != NULL)
+  {
+    value->range.lower = lowervalue;
+    value->range.upper = uppervalue;
+  }
 
-          if (tag != IPP_TAG_END_COLLECTION)
-            value = attr->values + attr->num_values;
-         else
-           value = NULL;
+  return (value != NULL);
+}
 
-         if ((*cb)(src, buffer, 2) < 2)
-         {
-           DEBUG_puts("1ippReadIO: unable to read value length.");
-           ipp_buffer_release(buffer);
-           return (IPP_ERROR);
-         }
 
-         n = (buffer[0] << 8) | buffer[1];
-          DEBUG_printf(("2ippReadIO: value length=%d", n));
+/*
+ * 'ippSetRequestId()' - Set the request ID in an IPP message.
+ *
+ * The @code ipp@ parameter refers to an IPP message previously created using the
+ * @link ippNew@ or @link ippNewRequest@ functions.
+ *
+ * The @code request_id@ parameter must be greater than 0.
+ *
+ * @since CUPS 1.6@
+ */
 
-         if (n >= IPP_BUF_SIZE)
-         {
-           _cupsSetError(IPP_ERROR,
-                         _("IPP value larger than 32767 bytes."), 1);
-           DEBUG_printf(("1ippReadIO: bad value length %d.", n));
-           ipp_buffer_release(buffer);
-           return (IPP_ERROR);
-         }
+int                                    /* O - 1 on success, 0 on failure */
+ippSetRequestId(ipp_t *ipp,            /* I - IPP message */
+                int   request_id)      /* I - Request ID */
+{
+ /*
+  * Range check input; not checking request_id values since ipptool wants to send
+  * invalid values for conformance testing and a bad request_id does not affect the
+  * encoding of a message...
+  */
 
-         switch (tag)
-         {
-           case IPP_TAG_INTEGER :
-           case IPP_TAG_ENUM :
-               if (n != 4)
-               {
-                 if (tag == IPP_TAG_INTEGER)
-                   _cupsSetError(IPP_ERROR,
-                                 _("IPP integer value not 4 bytes."), 1);
-                 else
-                   _cupsSetError(IPP_ERROR,
-                                 _("IPP enum value not 4 bytes."), 1);
-                 DEBUG_printf(("1ippReadIO: bad value length %d.", n));
-                 ipp_buffer_release(buffer);
-                 return (IPP_ERROR);
-               }
+  if (!ipp)
+    return (0);
 
-               if ((*cb)(src, buffer, 4) < 4)
-               {
-                 DEBUG_puts("1ippReadIO: Unable to read integer value.");
-                 ipp_buffer_release(buffer);
-                 return (IPP_ERROR);
-               }
+ /*
+  * Set the request ID and return...
+  */
 
-               n = (((((buffer[0] << 8) | buffer[1]) << 8) | buffer[2]) << 8) |
-                   buffer[3];
+  ipp->request.any.request_id = request_id;
 
-                if (attr->value_tag == IPP_TAG_RANGE)
-                  value->range.lower = value->range.upper = n;
-                else
-                 value->integer = n;
-               break;
+  return (1);
+}
 
-           case IPP_TAG_BOOLEAN :
-               if (n != 1)
-               {
-                 _cupsSetError(IPP_ERROR, _("IPP boolean value not 1 byte."),
-                               1);
-                 DEBUG_printf(("1ippReadIO: bad value length %d.", n));
-                 ipp_buffer_release(buffer);
-                 return (IPP_ERROR);
-               }
 
-               if ((*cb)(src, buffer, 1) < 1)
-               {
-                 DEBUG_puts("1ippReadIO: Unable to read boolean value.");
-                 ipp_buffer_release(buffer);
-                 return (IPP_ERROR);
-               }
+/*
+ * 'ippSetResolution()' - Set a resolution value in an attribute.
+ *
+ * The @code ipp@ parameter refers to the IPP message containing the attribute that was
+ * previously created using the @link ippNew@ or @link ippNewRequest@ functions.
+ *
+ * The @code attr@ parameter may be modified as a result of setting the value.
+ *
+ * The @code element@ parameter specifies which value to set from 0 to
+ * @link ippGetCount(attr)@.
+ *
+ * @since CUPS 1.6@
+ */
 
-                value->boolean = buffer[0];
-               break;
+int                                    /* O  - 1 on success, 0 on failure */
+ippSetResolution(
+    ipp_t           *ipp,              /* I  - IPP message */
+    ipp_attribute_t **attr,            /* IO - IPP attribute */
+    int             element,           /* I  - Value number (0-based) */
+    ipp_res_t       unitsvalue,                /* I  - Resolution units */
+    int             xresvalue,         /* I  - Horizontal/cross feed resolution */
+    int             yresvalue)         /* I  - Vertical/feed resolution */
+{
+  _ipp_value_t *value;                 /* Current value */
 
-            case IPP_TAG_NOVALUE :
-           case IPP_TAG_NOTSETTABLE :
-           case IPP_TAG_DELETEATTR :
-           case IPP_TAG_ADMINDEFINE :
-              /*
-               * These value types are not supposed to have values, however
-               * some vendors (Brother) do not implement IPP correctly and so
-               * we need to map non-empty values to text...
-               */
 
-               if (attr->value_tag == tag)
-               {
-                 if (n == 0)
-                   break;
+ /*
+  * Range check input...
+  */
 
-                 attr->value_tag = IPP_TAG_TEXT;
-               }
+  if (!ipp || !attr || !*attr || (*attr)->value_tag != IPP_TAG_RESOLUTION ||
+      element < 0 || element > (*attr)->num_values || xresvalue <= 0 || yresvalue <= 0 ||
+      unitsvalue < IPP_RES_PER_INCH || unitsvalue > IPP_RES_PER_CM)
+    return (0);
 
-           case IPP_TAG_TEXT :
-           case IPP_TAG_NAME :
-           case IPP_TAG_KEYWORD :
-           case IPP_TAG_URI :
-           case IPP_TAG_URISCHEME :
-           case IPP_TAG_CHARSET :
-           case IPP_TAG_LANGUAGE :
-           case IPP_TAG_MIMETYPE :
-               if ((*cb)(src, buffer, n) < n)
-               {
-                 DEBUG_puts("1ippReadIO: unable to read string value.");
-                 ipp_buffer_release(buffer);
-                 return (IPP_ERROR);
-               }
+ /*
+  * Set the value and return...
+  */
 
-               buffer[n] = '\0';
-               value->string.text = _cupsStrAlloc((char *)buffer);
-               DEBUG_printf(("2ippReadIO: value=\"%s\"", value->string.text));
-               break;
+  if ((value = ipp_set_value(ipp, attr, element)) != NULL)
+  {
+    value->resolution.units = unitsvalue;
+    value->resolution.xres  = xresvalue;
+    value->resolution.yres  = yresvalue;
+  }
 
-           case IPP_TAG_DATE :
-               if (n != 11)
-               {
-                 _cupsSetError(IPP_ERROR, _("IPP date value not 11 bytes."),
-                               1);
-                 DEBUG_printf(("1ippReadIO: bad value length %d.", n));
-                 ipp_buffer_release(buffer);
-                 return (IPP_ERROR);
-               }
+  return (value != NULL);
+}
 
-               if ((*cb)(src, value->date, 11) < 11)
-               {
-                 DEBUG_puts("1ippReadIO: Unable to read date value.");
-                 ipp_buffer_release(buffer);
-                 return (IPP_ERROR);
-               }
-               break;
 
-           case IPP_TAG_RESOLUTION :
-               if (n != 9)
-               {
-                 _cupsSetError(IPP_ERROR,
-                               _("IPP resolution value not 9 bytes."), 1);
-                 DEBUG_printf(("1ippReadIO: bad value length %d.", n));
-                 ipp_buffer_release(buffer);
-                 return (IPP_ERROR);
-               }
+/*
+ * 'ippSetStatusCode()' - Set the status code in an IPP response or event message.
+ *
+ * The @code ipp@ parameter refers to an IPP message previously created using the
+ * @link ippNew@ or @link ippNewRequest@ functions.
+ *
+ * @since CUPS 1.6@
+ */
 
-               if ((*cb)(src, buffer, 9) < 9)
-               {
-                 DEBUG_puts("1ippReadIO: Unable to read resolution value.");
-                 ipp_buffer_release(buffer);
-                 return (IPP_ERROR);
-               }
+int                                    /* O - 1 on success, 0 on failure */
+ippSetStatusCode(ipp_t        *ipp,    /* I - IPP response or event message */
+                 ipp_status_t status)  /* I - Status code */
+{
+ /*
+  * Range check input...
+  */
+
+  if (!ipp)
+    return (0);
 
-                value->resolution.xres =
-                   (((((buffer[0] << 8) | buffer[1]) << 8) | buffer[2]) << 8) |
-                   buffer[3];
-                value->resolution.yres =
-                   (((((buffer[4] << 8) | buffer[5]) << 8) | buffer[6]) << 8) |
-                   buffer[7];
-                value->resolution.units =
-                   (ipp_res_t)buffer[8];
-               break;
+ /*
+  * Set the status code and return...
+  */
 
-           case IPP_TAG_RANGE :
-               if (n != 8)
-               {
-                 _cupsSetError(IPP_ERROR,
-                               _("IPP rangeOfInteger value not 8 bytes."), 1);
-                 DEBUG_printf(("1ippReadIO: bad value length %d.", n));
-                 ipp_buffer_release(buffer);
-                 return (IPP_ERROR);
-               }
+  ipp->request.status.status_code = status;
 
-               if ((*cb)(src, buffer, 8) < 8)
-               {
-                 DEBUG_puts("1ippReadIO: Unable to read range value.");
-                 ipp_buffer_release(buffer);
-                 return (IPP_ERROR);
-               }
+  return (1);
 
-                value->range.lower =
-                   (((((buffer[0] << 8) | buffer[1]) << 8) | buffer[2]) << 8) |
-                   buffer[3];
-                value->range.upper =
-                   (((((buffer[4] << 8) | buffer[5]) << 8) | buffer[6]) << 8) |
-                   buffer[7];
-               break;
+}
 
-           case IPP_TAG_TEXTLANG :
-           case IPP_TAG_NAMELANG :
-               if (n < 4)
-               {
-                 if (tag == IPP_TAG_TEXTLANG)
-                   _cupsSetError(IPP_ERROR,
-                                 _("IPP textWithLanguage value less than "
-                                   "minimum 4 bytes."), 1);
-                 else
-                   _cupsSetError(IPP_ERROR,
-                                 _("IPP nameWithLanguage value less than "
-                                   "minimum 4 bytes."), 1);
-                 DEBUG_printf(("1ippReadIO: bad value length %d.", n));
-                 ipp_buffer_release(buffer);
-                 return (IPP_ERROR);
-               }
 
-               if ((*cb)(src, buffer, n) < n)
-               {
-                 DEBUG_puts("1ippReadIO: Unable to read string w/language "
-                            "value.");
-                 ipp_buffer_release(buffer);
-                 return (IPP_ERROR);
-               }
+/*
+ * 'ippSetString()' - Set a string value in an attribute.
+ *
+ * The @code ipp@ parameter refers to the IPP message containing the attribute that was
+ * previously created using the @link ippNew@ or @link ippNewRequest@ functions.
+ *
+ * The @code attr@ parameter may be modified as a result of setting the value.
+ *
+ * The @code element@ parameter specifies which value to set from 0 to
+ * @link ippGetCount(attr)@.
+ *
+ * @since CUPS 1.6@
+ */
 
-                bufptr = buffer;
+int                                    /* O  - 1 on success, 0 on failure */
+ippSetString(ipp_t           *ipp,     /* I  - IPP message */
+             ipp_attribute_t **attr,   /* IO - IPP attribute */
+             int             element,  /* I  - Value number (0-based) */
+            const char      *strvalue) /* I  - String value */
+{
+  char         *temp;                  /* Temporary string */
+  _ipp_value_t *value;                 /* Current value */
 
-              /*
-               * text-with-language and name-with-language are composite
-               * values:
-               *
-               *    language-length
-               *    language
-               *    text-length
-               *    text
-               *
-               * The "charset" field name is an unfortunate typo from
-               * CUPS 1.0...
-               */
 
-               n = (bufptr[0] << 8) | bufptr[1];
+ /*
+  * Range check input...
+  */
 
-               if ((bufptr + 2 + n) >= (buffer + IPP_BUF_SIZE) ||
-                   n >= sizeof(string))
-               {
-                 _cupsSetError(IPP_ERROR,
-                               _("IPP language length overflows value."), 1);
-                 DEBUG_printf(("1ippReadIO: bad value length %d.", n));
-                 ipp_buffer_release(buffer);
-                 return (IPP_ERROR);
-               }
+  if (!ipp || !attr || !*attr || (*attr)->value_tag != IPP_TAG_INTEGER ||
+      element < 0 || element > (*attr)->num_values || !strvalue)
+    return (0);
 
-               memcpy(string, bufptr + 2, n);
-               string[n] = '\0';
+ /*
+  * Set the value and return...
+  */
 
-               value->string.charset = _cupsStrAlloc((char *)string);
+  if ((value = ipp_set_value(ipp, attr, element)) != NULL)
+  {
+    if (element > 0)
+      value->string.language = (*attr)->values[0].string.language;
 
-                bufptr += 2 + n;
-               n = (bufptr[0] << 8) | bufptr[1];
+    if ((int)((*attr)->value_tag) & IPP_TAG_COPY)
+      value->string.text = (char *)strvalue;
+    else if ((temp = _cupsStrAlloc(strvalue)) != NULL)
+    {
+      if (value->string.text)
+        _cupsStrFree(value->string.text);
 
-               if ((bufptr + 2 + n) >= (buffer + IPP_BUF_SIZE))
-               {
-                 _cupsSetError(IPP_ERROR,
-                               _("IPP string length overflows value."), 1);
-                 DEBUG_printf(("1ippReadIO: bad value length %d.", n));
-                 ipp_buffer_release(buffer);
-                 return (IPP_ERROR);
-               }
+      value->string.text = temp;
+    }
+    else
+      return (0);
+  }
 
-               bufptr[2 + n] = '\0';
-                value->string.text = _cupsStrAlloc((char *)bufptr + 2);
-               break;
+  return (value != NULL);
+}
 
-            case IPP_TAG_BEGIN_COLLECTION :
-              /*
-               * Oh, boy, here comes a collection value, so read it...
-               */
 
-                value->collection = ippNew();
+/*
+ * 'ippSetValueTag()' - Set the value tag of an attribute.
+ *
+ * The @code ipp@ parameter refers to the IPP message containing the attribute that was
+ * previously created using the @link ippNew@ or @link ippNewRequest@ functions.
+ *
+ * The @code attr@ parameter may be modified as a result of setting the value.
+ *
+ * Integer (@code IPP_TAG_INTEGER@) values can be promoted to rangeOfInteger
+ * (@code IPP_TAG_RANGE@) values, the various string tags can be promoted to name
+ * (@code IPP_TAG_NAME@) or nameWithLanguage (@code IPP_TAG_NAMELANG@) values, text
+ * (@code IPP_TAG_TEXT@) values can be promoted to textWithLanguage
+ * (@code IPP_TAG_TEXTLANG@) values, and all values can be demoted to the various
+ * out-of-band value tags such as no-value (@code IPP_TAG_NOVALUE@). All other changes
+ * will be rejected.
+ *
+ * Promoting a string attribute to nameWithLanguage or textWithLanguage adds the language
+ * code in the "attributes-natural-language" attribute or, if not present, the language
+ * code for the current locale.
+ *
+ * @since CUPS 1.6@
+ */
 
-                if (n > 0)
-               {
-                 _cupsSetError(IPP_ERROR,
-                               _("IPP begCollection value not 0 bytes."), 1);
-                 DEBUG_puts("1ippReadIO: begCollection tag with value length "
-                            "> 0.");
-                 ipp_buffer_release(buffer);
-                 return (IPP_ERROR);
-               }
+int                                    /* O  - 1 on success, 0 on failure */
+ippSetValueTag(
+    ipp_t          *ipp,               /* I  - IPP message */
+    ipp_attribute_t **attr,            /* IO - IPP attribute */
+    ipp_tag_t       value_tag)         /* I  - Value tag */
+{
+  int          i;                      /* Looping var */
+  _ipp_value_t *value;                 /* Current value */
+  int          integer;                /* Current integer value */
+  cups_lang_t  *language;              /* Current language */
+  char         code[32];               /* Language code */
+  ipp_tag_t    temp_tag;               /* Temporary value tag */
 
-               if (ippReadIO(src, cb, 1, ipp, value->collection) == IPP_ERROR)
-               {
-                 DEBUG_puts("1ippReadIO: Unable to read collection value.");
-                 ipp_buffer_release(buffer);
-                 return (IPP_ERROR);
-               }
-                break;
 
-            case IPP_TAG_END_COLLECTION :
-               ipp_buffer_release(buffer);
+ /*
+  * Range check input...
+  */
 
-                if (n > 0)
-               {
-                 _cupsSetError(IPP_ERROR,
-                               _("IPP endCollection value not 0 bytes."), 1);
-                 DEBUG_puts("1ippReadIO: endCollection tag with value length "
-                            "> 0.");
-                 return (IPP_ERROR);
-               }
+  if (!ipp || !attr)
+    return (0);
 
-               DEBUG_puts("1ippReadIO: endCollection tag...");
-               return (ipp->state = IPP_DATA);
+ /*
+  * If there is no change, return immediately...
+  */
 
-            case IPP_TAG_MEMBERNAME :
-              /*
-               * The value the name of the member in the collection, which
-               * we need to carry over...
-               */
+  if (value_tag == (*attr)->value_tag)
+    return (1);
 
-               if ((*cb)(src, buffer, n) < n)
-               {
-                 DEBUG_puts("1ippReadIO: Unable to read member name value.");
-                 ipp_buffer_release(buffer);
-                 return (IPP_ERROR);
-               }
+ /*
+  * Otherwise implement changes as needed...
+  */
 
-               buffer[n] = '\0';
-               attr->name = _cupsStrAlloc((char *)buffer);
+  temp_tag = (ipp_tag_t)((int)((*attr)->value_tag) & IPP_TAG_MASK);
 
-               /*
-               * Since collection members are encoded differently than
-               * regular attributes, make sure we don't start with an
-               * empty value...
-               */
+  switch (value_tag)
+  {
+    case IPP_TAG_UNSUPPORTED_VALUE :
+    case IPP_TAG_DEFAULT :
+    case IPP_TAG_UNKNOWN :
+    case IPP_TAG_NOVALUE :
+    case IPP_TAG_NOTSETTABLE :
+    case IPP_TAG_DELETEATTR :
+    case IPP_TAG_ADMINDEFINE :
+       /*
+        * Free any existing values...
+        */
 
-                attr->num_values --;
+        if ((*attr)->num_values > 0)
+          ipp_free_values(*attr, 0, (*attr)->num_values);
 
-               DEBUG_printf(("2ippReadIO: member name=\"%s\"", attr->name));
-               break;
+       /*
+        * Set out-of-band value...
+        */
 
-            default : /* Other unsupported values */
-                value->unknown.length = n;
-               if (n > 0)
-               {
-                 if ((value->unknown.data = malloc(n)) == NULL)
-                 {
-                   _cupsSetHTTPError(HTTP_ERROR);
-                   DEBUG_puts("1ippReadIO: Unable to allocate value");
-                   ipp_buffer_release(buffer);
-                   return (IPP_ERROR);
-                 }
+        (*attr)->value_tag = value_tag;
+        break;
 
-                 if ((*cb)(src, value->unknown.data, n) < n)
-                 {
-                   DEBUG_puts("1ippReadIO: Unable to read unsupported value.");
-                   ipp_buffer_release(buffer);
-                   return (IPP_ERROR);
-                 }
-               }
-               else
-                 value->unknown.data = NULL;
-               break;
-         }
+    case IPP_TAG_RANGE :
+        if (temp_tag != IPP_TAG_INTEGER)
+          return (0);
+
+        for (i = (*attr)->num_values, value = (*attr)->values;
+             i > 0;
+             i --, value ++)
+        {
+          integer            = value->integer;
+          value->range.lower = value->range.upper = integer;
+        }
 
-          attr->num_values ++;
+        (*attr)->value_tag = IPP_TAG_RANGE;
+        break;
 
-        /*
-          * If blocking is disabled, stop here...
-         */
+    case IPP_TAG_NAME :
+        if (temp_tag != IPP_TAG_KEYWORD && temp_tag != IPP_TAG_URI &&
+            temp_tag != IPP_TAG_URISCHEME && temp_tag != IPP_TAG_LANGUAGE &&
+            temp_tag != IPP_TAG_MIMETYPE)
+          return (0);
 
-          if (!blocking)
-           break;
-       }
+        (*attr)->value_tag = (ipp_tag_t)(IPP_TAG_NAME | ((*attr)->value_tag & IPP_TAG_COPY));
         break;
 
-    case IPP_DATA :
+    case IPP_TAG_NAMELANG :
+    case IPP_TAG_TEXTLANG :
+        if (value_tag == IPP_TAG_NAMELANG &&
+            (temp_tag != IPP_TAG_NAME && temp_tag != IPP_TAG_KEYWORD &&
+             temp_tag != IPP_TAG_URI && temp_tag != IPP_TAG_URISCHEME &&
+             temp_tag != IPP_TAG_LANGUAGE && temp_tag != IPP_TAG_MIMETYPE))
+          return (0);
+
+        if (value_tag == IPP_TAG_TEXTLANG && temp_tag != IPP_TAG_TEXT)
+          return (0);
+
+        if (ipp->attrs && ipp->attrs->next && ipp->attrs->next->name &&
+            !strcmp(ipp->attrs->next->name, "attributes-natural-language"))
+        {
+         /*
+          * Use the language code from the IPP message...
+          */
+
+         (*attr)->values[0].string.language =
+             _cupsStrAlloc(ipp->attrs->next->values[0].string.text);
+        }
+        else
+        {
+         /*
+          * Otherwise, use the language code corresponding to the locale...
+          */
+
+         language = cupsLangDefault();
+         (*attr)->values[0].string.language = _cupsStrAlloc(ipp_lang_code(language->language,
+                                                                       code,
+                                                                       sizeof(code)));
+        }
+
+        for (i = (*attr)->num_values - 1, value = (*attr)->values + 1;
+             i > 0;
+             i --, value ++)
+          value->string.language = (*attr)->values[0].string.language;
+
+        if ((int)(*attr)->value_tag & IPP_TAG_COPY)
+        {
+         /*
+          * Make copies of all values...
+          */
+
+         for (i = (*attr)->num_values, value = (*attr)->values;
+              i > 0;
+              i --, value ++)
+           value->string.text = _cupsStrAlloc(value->string.text);
+        }
+
+        (*attr)->value_tag = IPP_TAG_NAMELANG;
         break;
 
+    case IPP_TAG_KEYWORD :
+        if (temp_tag == IPP_TAG_NAME || temp_tag == IPP_TAG_NAMELANG)
+          break;                       /* Silently "allow" name -> keyword */
+
     default :
-        break; /* anti-compiler-warning-code */
+        return (0);
   }
 
-  DEBUG_printf(("1ippReadIO: returning ipp->state=%d.", ipp->state));
-  ipp_buffer_release(buffer);
+  return (1);
+}
+
+
+/*
+ * 'ippSetVersion()' - Set the version number in an IPP message.
+ *
+ * The @code ipp@ parameter refers to an IPP message previously created using the
+ * @link ippNew@ or @link ippNewRequest@ functions.
+ *
+ * The valid version numbers are currently 1.0, 1.1, 2.0, 2.1, and 2.2.
+ *
+ * @since CUPS 1.6@
+ */
+
+int                                    /* O - 1 on success, 0 on failure */
+ippSetVersion(ipp_t *ipp,              /* I - IPP message */
+              int   major,             /* I - Major version number (major.minor) */
+              int   minor)             /* I - Minor version number (major.minor) */
+{
+ /*
+  * Range check input...
+  */
+
+  if (!ipp || major < 0 || minor < 0)
+    return (0);
+
+ /*
+  * Set the version number...
+  */
+
+  ipp->request.any.version[0] = major;
+  ipp->request.any.version[1] = minor;
 
-  return (ipp->state);
+  return (1);
 }
 
 
@@ -1931,7 +3793,7 @@ ippWriteIO(void       *dst,               /* I - Destination */
   unsigned char                *buffer,        /* Data buffer */
                        *bufptr;        /* Pointer into buffer */
   ipp_attribute_t      *attr;          /* Current attribute */
-  ipp_value_t          *value;         /* Current value */
+  _ipp_value_t         *value;         /* Current value */
 
 
   DEBUG_printf(("ippWriteIO(dst=%p, cb=%p, blocking=%d, parent=%p, ipp=%p)",
@@ -2044,9 +3906,7 @@ ippWriteIO(void       *dst,               /* I - Destination */
                        ippTagString(attr->value_tag)));
 
          /*
-         * Write the attribute tag and name.  The current implementation
-         * does not support the extension value tags above 0x7f, so all
-         * value tags are 1 byte.
+         * Write the attribute tag and name.
          *
          * The attribute name length does not include the trailing nul
          * character in the source string.
@@ -2061,7 +3921,7 @@ ippWriteIO(void       *dst,               /* I - Destination */
            * overflow the buffer...
            */
 
-            if ((n = (int)strlen(attr->name)) > (IPP_BUF_SIZE - 4))
+            if ((n = (int)strlen(attr->name)) > (IPP_BUF_SIZE - 8))
            {
              DEBUG_printf(("1ippWriteIO: Attribute name too long (%d)", n));
              ipp_buffer_release(buffer);
@@ -2077,7 +3937,17 @@ ippWriteIO(void       *dst,              /* I - Destination */
             DEBUG_printf(("2ippWriteIO: writing name=%d,\"%s\"", n,
                          attr->name));
 
-            *bufptr++ = attr->value_tag;
+            if (attr->value_tag > 0xff)
+            {
+              *bufptr++ = IPP_TAG_EXTENSION;
+             *bufptr++ = attr->value_tag >> 24;
+             *bufptr++ = attr->value_tag >> 16;
+             *bufptr++ = attr->value_tag >> 8;
+             *bufptr++ = attr->value_tag;
+            }
+            else
+             *bufptr++ = attr->value_tag;
+
            *bufptr++ = n >> 8;
            *bufptr++ = n;
            memcpy(bufptr, attr->name, n);
@@ -2090,7 +3960,7 @@ ippWriteIO(void       *dst,               /* I - Destination */
            * overflow the buffer...
            */
 
-            if ((n = (int)strlen(attr->name)) > (IPP_BUF_SIZE - 7))
+            if ((n = (int)strlen(attr->name)) > (IPP_BUF_SIZE - 12))
            {
              DEBUG_printf(("1ippWriteIO: Attribute name too long (%d)", n));
              ipp_buffer_release(buffer);
@@ -2118,7 +3988,17 @@ ippWriteIO(void       *dst,              /* I - Destination */
            memcpy(bufptr, attr->name, n);
            bufptr += n;
 
-            *bufptr++ = attr->value_tag;
+            if (attr->value_tag > 0xff)
+            {
+              *bufptr++ = IPP_TAG_EXTENSION;
+             *bufptr++ = attr->value_tag >> 24;
+             *bufptr++ = attr->value_tag >> 16;
+             *bufptr++ = attr->value_tag >> 8;
+             *bufptr++ = attr->value_tag;
+            }
+            else
+             *bufptr++ = attr->value_tag;
+
             *bufptr++ = 0;
             *bufptr++ = 0;
          }
@@ -2129,6 +4009,17 @@ ippWriteIO(void       *dst,              /* I - Destination */
 
          switch (attr->value_tag & ~IPP_TAG_COPY)
          {
+           case IPP_TAG_UNSUPPORTED_VALUE :
+           case IPP_TAG_DEFAULT :
+           case IPP_TAG_UNKNOWN :
+           case IPP_TAG_NOVALUE :
+           case IPP_TAG_NOTSETTABLE :
+           case IPP_TAG_DELETEATTR :
+           case IPP_TAG_ADMINDEFINE :
+               *bufptr++ = 0;
+               *bufptr++ = 0;
+               break;
+
            case IPP_TAG_INTEGER :
            case IPP_TAG_ENUM :
                for (i = 0, value = attr->values;
@@ -2501,8 +4392,8 @@ ippWriteIO(void       *dst,               /* I - Destination */
 
                   n = 4;
 
-                 if (value->string.charset != NULL)
-                    n += (int)strlen(value->string.charset);
+                 if (value->string.language != NULL)
+                    n += (int)strlen(value->string.language);
 
                  if (value->string.text != NULL)
                     n += (int)strlen(value->string.text);
@@ -2532,19 +4423,19 @@ ippWriteIO(void       *dst,             /* I - Destination */
                  *bufptr++ = n >> 8;
                  *bufptr++ = n;
 
-                 /* Length of charset */
-                 if (value->string.charset != NULL)
-                   n = (int)strlen(value->string.charset);
+                 /* Length of language */
+                 if (value->string.language != NULL)
+                   n = (int)strlen(value->string.language);
                  else
                    n = 0;
 
                  *bufptr++ = n >> 8;
                  *bufptr++ = n;
 
-                 /* Charset */
+                 /* Language */
                  if (n > 0)
                  {
-                   memcpy(bufptr, value->string.charset, n);
+                   memcpy(bufptr, value->string.language, n);
                    bufptr += n;
                  }
 
@@ -2782,122 +4673,71 @@ ippWriteIO(void       *dst,            /* I - Destination */
 
 
 /*
- * '_ippAddAttr()' - Add a new attribute to the request.
+ * 'ipp_add_attr()' - Add a new attribute to the message.
  */
 
-ipp_attribute_t *                      /* O - New attribute */
-_ippAddAttr(ipp_t *ipp,                        /* I - IPP message */
-            int   num_values)          /* I - Number of values */
+static ipp_attribute_t *               /* O - New attribute */
+ipp_add_attr(ipp_t      *ipp,          /* I - IPP message */
+             const char *name,         /* I - Attribute name or NULL */
+             ipp_tag_t  group_tag,     /* I - Group tag or IPP_TAG_ZERO */
+             ipp_tag_t  value_tag,     /* I - Value tag or IPP_TAG_ZERO */
+             int        num_values)    /* I - Number of values */
 {
+  int                  alloc_values;   /* Number of values to allocate */
   ipp_attribute_t      *attr;          /* New attribute */
 
 
-  DEBUG_printf(("4_ippAddAttr(ipp=%p, num_values=%d)", ipp, num_values));
+  DEBUG_printf(("4ipp_add_attr(ipp=%p, name=\"%s\", group_tag=0x%x, value_tag=0x%x, "
+                "num_values=%d)", ipp, name, group_tag, value_tag, num_values));
+
+ /*
+  * Range check input...
+  */
 
   if (!ipp || num_values < 0)
     return (NULL);
 
-  attr = calloc(sizeof(ipp_attribute_t) +
-                (num_values - 1) * sizeof(ipp_value_t), 1);
-
-  if (attr != NULL)
-  {
-    attr->num_values = num_values;
-
-    if (ipp->last == NULL)
-      ipp->attrs = attr;
-    else
-      ipp->last->next = attr;
-
-    ipp->last = attr;
-  }
-
-  DEBUG_printf(("5_ippAddAttr: Returning %p", attr));
-
-  return (attr);
-}
-
-
-/*
- * '_ippFreeAttr()' - Free an attribute.
- */
-
-void
-_ippFreeAttr(ipp_attribute_t *attr)    /* I - Attribute to free */
-{
-  int          i;                      /* Looping var */
-  ipp_value_t  *value;                 /* Current value */
+ /*
+  * Allocate memory, rounding the allocation up as needed...
+  */
 
+  if (num_values <= 1)
+    alloc_values = num_values;
+  else
+    alloc_values = (num_values + IPP_MAX_VALUES - 1) & ~(IPP_MAX_VALUES - 1);
 
-  DEBUG_printf(("4_ippFreeAttr(attr=%p)", attr));
+  attr = calloc(sizeof(ipp_attribute_t) +
+                (alloc_values - 1) * sizeof(_ipp_value_t), 1);
 
-  switch (attr->value_tag)
+  if (attr)
   {
-    case IPP_TAG_TEXT :
-    case IPP_TAG_NAME :
-    case IPP_TAG_RESERVED_STRING :
-    case IPP_TAG_KEYWORD :
-    case IPP_TAG_URI :
-    case IPP_TAG_URISCHEME :
-    case IPP_TAG_CHARSET :
-    case IPP_TAG_LANGUAGE :
-    case IPP_TAG_MIMETYPE :
-       for (i = 0, value = attr->values;
-            i < attr->num_values;
-            i ++, value ++)
-         _cupsStrFree(value->string.text);
-       break;
+   /*
+    * Initialize attribute...
+    */
 
-    case IPP_TAG_TEXTLANG :
-    case IPP_TAG_NAMELANG :
-       for (i = 0, value = attr->values;
-            i < attr->num_values;
-            i ++, value ++)
-       {
-         if (value->string.charset && i == 0)
-           _cupsStrFree(value->string.charset);
-         _cupsStrFree(value->string.text);
-       }
-       break;
+    if (name)
+      attr->name = _cupsStrAlloc(name);
 
-    case IPP_TAG_INTEGER :
-    case IPP_TAG_ENUM :
-    case IPP_TAG_BOOLEAN :
-    case IPP_TAG_DATE :
-    case IPP_TAG_RESOLUTION :
-    case IPP_TAG_RANGE :
-       break;
+    attr->group_tag  = group_tag;
+    attr->value_tag  = value_tag;
+    attr->num_values = num_values;
 
-    case IPP_TAG_BEGIN_COLLECTION :
-       for (i = 0, value = attr->values;
-            i < attr->num_values;
-            i ++, value ++)
-          ippDelete(value->collection);
-       break;
+   /*
+    * Add it to the end of the linked list...
+    */
 
-    case IPP_TAG_STRING :
-       for (i = 0, value = attr->values;
-            i < attr->num_values;
-            i ++, value ++)
-         free(value->unknown.data);
-        break;
+    if (ipp->last)
+      ipp->last->next = attr;
+    else
+      ipp->attrs = attr;
 
-    default :
-        if (!((int)attr->value_tag & IPP_TAG_COPY))
-       {
-         for (i = 0, value = attr->values;
-              i < attr->num_values;
-              i ++, value ++)
-            if (value->unknown.data)
-             free(value->unknown.data);
-        }
-       break;
+    ipp->prev = ipp->last;
+    ipp->last = ipp->current = attr;
   }
 
-  if (attr->name)
-    _cupsStrFree(attr->name);
+  DEBUG_printf(("5ipp_add_attr: Returning %p", attr));
 
-  free(attr);
+  return (attr);
 }
 
 
@@ -2942,6 +4782,157 @@ ipp_buffer_release(unsigned char *b)    /* I - Buffer to release */
 }
 
 
+/*
+ * 'ipp_free_values()' - Free attribute values.
+ */
+
+static void
+ipp_free_values(ipp_attribute_t *attr, /* I - Attribute to free values from */
+                int             element,/* I - First value to free */
+                int             count) /* I - Number of values to free */
+{
+  int          i;                      /* Looping var */
+  _ipp_value_t *value;                 /* Current value */
+
+
+  DEBUG_printf(("4ipp_free_values(attr=%p, element=%d, count=%d)", attr, element, count));
+
+  if (!(attr->value_tag & IPP_TAG_COPY))
+  {
+   /*
+    * Free values as needed...
+    */
+
+    switch (attr->value_tag)
+    {
+      case IPP_TAG_TEXTLANG :
+      case IPP_TAG_NAMELANG :
+         if (element == 0 && count == attr->num_values && attr->values[0].string.language)
+           _cupsStrFree(attr->values[0].string.language);
+
+      case IPP_TAG_TEXT :
+      case IPP_TAG_NAME :
+      case IPP_TAG_RESERVED_STRING :
+      case IPP_TAG_KEYWORD :
+      case IPP_TAG_URI :
+      case IPP_TAG_URISCHEME :
+      case IPP_TAG_CHARSET :
+      case IPP_TAG_LANGUAGE :
+      case IPP_TAG_MIMETYPE :
+         for (i = count, value = attr->values + element;
+              i > 0;
+              i --, value ++)
+           _cupsStrFree(value->string.text);
+         break;
+
+      case IPP_TAG_DEFAULT :
+      case IPP_TAG_UNKNOWN :
+      case IPP_TAG_NOVALUE :
+      case IPP_TAG_NOTSETTABLE :
+      case IPP_TAG_DELETEATTR :
+      case IPP_TAG_ADMINDEFINE :
+      case IPP_TAG_INTEGER :
+      case IPP_TAG_ENUM :
+      case IPP_TAG_BOOLEAN :
+      case IPP_TAG_DATE :
+      case IPP_TAG_RESOLUTION :
+      case IPP_TAG_RANGE :
+         break;
+
+      case IPP_TAG_BEGIN_COLLECTION :
+         for (i = count, value = attr->values + element;
+              i > 0;
+              i --, value ++)
+           ippDelete(value->collection);
+         break;
+
+      case IPP_TAG_STRING :
+      default :
+         for (i = count, value = attr->values + element;
+              i > 0;
+              i --, value ++)
+           if (value->unknown.data)
+             free(value->unknown.data);
+         break;
+    }
+  }
+
+ /*
+  * If we are not freeing values from the end, move the remaining values up...
+  */
+
+  if ((element + count) < attr->num_values)
+    memmove(attr->values + element, attr->values + element + count,
+            (attr->num_values - count - element) * sizeof(_ipp_value_t));
+
+  attr->num_values -= count;
+}
+
+
+/*
+ * 'ipp_get_code()' - Convert a C locale/charset name into an IPP language/charset code.
+ *
+ * This typically converts strings of the form "ll_CC", "ll-REGION", and "CHARSET_NUMBER"
+ * to "ll-cc", "ll-region", and "charset-number", respectively.
+ */
+
+static char *                          /* O - Language code string */
+ipp_get_code(const char *value,                /* I - Locale/charset string */
+             char       *buffer,       /* I - String buffer */
+             size_t     bufsize)       /* I - Size of string buffer */
+{
+  char *bufptr,                        /* Pointer into buffer */
+       *bufend;                        /* End of buffer */
+
+
+ /*
+  * Convert values to lowercase and change _ to - as needed...
+  */
+
+  for (bufptr = buffer, bufend = buffer + bufsize - 1;
+       *value && bufptr < bufend;
+       value ++)
+    if (*value == '_')
+      *bufptr++ = '-';
+    else
+      *bufptr++ = _cups_tolower(*value);
+
+  *bufptr = '\0';
+
+ /*
+  * Return the converted string...
+  */
+
+  return (buffer);
+}
+
+
+/*
+ * 'ipp_lang_code()' - Convert a C locale name into an IPP language code.
+ *
+ * This typically converts strings of the form "ll_CC" and "ll-REGION" to "ll-cc" and
+ * "ll-region", respectively.  It also converts the "C" (POSIX) locale to "en".
+ */
+
+static char *                          /* O - Language code string */
+ipp_lang_code(const char *locale,      /* I - Locale string */
+              char       *buffer,      /* I - String buffer */
+              size_t     bufsize)      /* I - Size of string buffer */
+{
+ /*
+  * Map POSIX ("C") locale to generic English, otherwise convert the locale string as-is.
+  */
+
+  if (!_cups_strcasecmp(locale, "c"))
+  {
+    strlcpy(buffer, "en", bufsize);
+    return (buffer);
+  }
+  else
+    return (ipp_get_code(locale, buffer, bufsize));
+}
+
+
 /*
  * 'ipp_length()' - Compute the length of an IPP message or collection value.
  */
@@ -2951,14 +4942,19 @@ ipp_length(ipp_t *ipp,                  /* I - IPP message or collection */
            int   collection)           /* I - 1 if a collection, 0 otherwise */
 {
   int                  i;              /* Looping var */
-  int                  bytes;          /* Number of bytes */
+  size_t               bytes;          /* Number of bytes */
   ipp_attribute_t      *attr;          /* Current attribute */
   ipp_tag_t            group;          /* Current group */
-  ipp_value_t          *value;         /* Current value */
+  _ipp_value_t         *value;         /* Current value */
+
 
+  DEBUG_printf(("3ipp_length(ipp=%p, collection=%d)", ipp, collection));
 
-  if (ipp == NULL)
+  if (!ipp)
+  {
+    DEBUG_puts("4ipp_length: Returning 0 bytes");
     return (0);
+  }
 
  /*
   * Start with 8 bytes for the IPP message header...
@@ -2986,12 +4982,15 @@ ipp_length(ipp_t *ipp,                  /* I - IPP message or collection */
     if (!attr->name)
       continue;
 
-    DEBUG_printf(("9ipp_length: attr->name=\"%s\", attr->num_values=%d, "
-                  "bytes=%d", attr->name, attr->num_values, bytes));
+    DEBUG_printf(("5ipp_length: attr->name=\"%s\", attr->num_values=%d, "
+                  "bytes=" CUPS_LLFMT, attr->name, attr->num_values, CUPS_LLCAST bytes));
 
-    bytes += (int)strlen(attr->name);  /* Name */
-    bytes += attr->num_values;         /* Value tag for each value */
+    if (attr->value_tag < IPP_TAG_EXTENSION)
+      bytes += attr->num_values;       /* Value tag for each value */
+    else
+      bytes += 5 * attr->num_values;   /* Value tag for each value */
     bytes += 2 * attr->num_values;     /* Name lengths */
+    bytes += (int)strlen(attr->name);  /* Name */
     bytes += 2 * attr->num_values;     /* Value lengths */
 
     if (collection)
@@ -2999,6 +4998,15 @@ ipp_length(ipp_t *ipp,                   /* I - IPP message or collection */
 
     switch (attr->value_tag & ~IPP_TAG_COPY)
     {
+      case IPP_TAG_UNSUPPORTED_VALUE :
+      case IPP_TAG_DEFAULT :
+      case IPP_TAG_UNKNOWN :
+      case IPP_TAG_NOVALUE :
+      case IPP_TAG_NOTSETTABLE :
+      case IPP_TAG_DELETEATTR :
+      case IPP_TAG_ADMINDEFINE :
+          break;
+
       case IPP_TAG_INTEGER :
       case IPP_TAG_ENUM :
           bytes += 4 * attr->num_values;
@@ -3019,8 +5027,8 @@ ipp_length(ipp_t *ipp,                    /* I - IPP message or collection */
          for (i = 0, value = attr->values;
               i < attr->num_values;
               i ++, value ++)
-           if (value->string.text != NULL)
-             bytes += (int)strlen(value->string.text);
+           if (value->string.text)
+             bytes += strlen(value->string.text);
          break;
 
       case IPP_TAG_DATE :
@@ -3043,11 +5051,11 @@ ipp_length(ipp_t *ipp,                  /* I - IPP message or collection */
               i < attr->num_values;
               i ++, value ++)
          {
-           if (value->string.charset != NULL)
-             bytes += (int)strlen(value->string.charset);
+           if (value->string.language)
+             bytes += strlen(value->string.language);
 
-           if (value->string.text != NULL)
-             bytes += (int)strlen(value->string.text);
+           if (value->string.text)
+             bytes += strlen(value->string.text);
          }
          break;
 
@@ -3055,7 +5063,7 @@ ipp_length(ipp_t *ipp,                    /* I - IPP message or collection */
          for (i = 0, value = attr->values;
               i < attr->num_values;
               i ++, value ++)
-            bytes += (int)ipp_length(value->collection, 1);
+            bytes += ipp_length(value->collection, 1);
          break;
 
       default :
@@ -3077,7 +5085,7 @@ ipp_length(ipp_t *ipp,                    /* I - IPP message or collection */
   else
     bytes ++;
 
-  DEBUG_printf(("8ipp_length: Returning %d bytes", bytes));
+  DEBUG_printf(("4ipp_length: Returning " CUPS_LLFMT " bytes", CUPS_LLCAST bytes));
 
   return (bytes);
 }
@@ -3231,6 +5239,126 @@ ipp_read_file(int         *fd,          /* I - File descriptor */
 }
 
 
+/*
+ * 'ipp_set_value()' - Get the value element from an attribute, expanding it as needed.
+ */
+
+static _ipp_value_t *                  /* O  - IPP value element or NULL on error */
+ipp_set_value(ipp_t           *ipp,    /* I  - IPP message */
+              ipp_attribute_t **attr,  /* IO - IPP attribute */
+              int             element) /* I  - Value number (0-based) */
+{
+  ipp_attribute_t      *temp,          /* New attribute pointer */
+                       *current,       /* Current attribute in list */
+                       *prev;          /* Previous attribute in list */
+  int                  alloc_values;   /* Allocated values */
+
+
+ /*
+  * If we are setting an existing value element, return it...
+  */
+
+  temp = *attr;
+
+  if (temp->num_values <= 1)
+    alloc_values = temp->num_values;
+  else
+    alloc_values = (temp->num_values + IPP_MAX_VALUES - 1) & ~(IPP_MAX_VALUES - 1);
+
+  if (element < alloc_values)
+    return (temp->values + element);
+
+ /*
+  * Otherwise re-allocate the attribute - we allocate in groups of IPP_MAX_VALUE values
+  * when num_values > 1.
+  */
+
+  if (alloc_values < IPP_MAX_VALUES)
+    alloc_values = IPP_MAX_VALUES;
+  else
+    alloc_values += IPP_MAX_VALUES;
+
+  DEBUG_printf(("4ipp_set_value: Reallocating for up to %d values.", alloc_values));
+
+ /*
+  * Reallocate memory...
+  */
+
+  if ((temp = realloc(temp, sizeof(ipp_attribute_t) +
+                           (temp->num_values + IPP_MAX_VALUES - 1) *
+                           sizeof(_ipp_value_t))) == NULL)
+  {
+    _cupsSetHTTPError(HTTP_ERROR);
+    DEBUG_puts("4ipp_set_value: Unable to resize attribute.");
+    return (NULL);
+  }
+
+ /*
+  * Zero the new memory...
+  */
+
+  memset(temp->values + temp->num_values, 0,
+         (alloc_values - temp->num_values) * sizeof(_ipp_value_t));
+
+  if (temp != *attr)
+  {
+   /*
+    * Reset pointers in the list...
+    */
+
+    if (ipp->current == *attr && ipp->prev)
+    {
+     /*
+      * Use current "previous" pointer...
+      */
+
+      prev = ipp->prev;
+    }
+    else
+    {
+     /*
+      * Find this attribute in the linked list...
+      */
+
+      for (prev = NULL, current = ipp->attrs;
+          current && current != *attr;
+          prev = current, current = current->next);
+
+      if (!current)
+      {
+       /*
+       * This is a serious error!
+       */
+
+       *attr = temp;
+       _cupsSetError(IPP_ERROR, _("IPP attribute is not a member of the message."), 1);
+       DEBUG_puts("4ipp_set_value: Unable to find attribute in message.");
+       return (NULL);
+      }
+    }
+
+    if (prev)
+      prev->next = temp;
+    else
+      ipp->attrs = temp;
+
+    ipp->current = temp;
+    ipp->prev    = prev;
+
+    if (ipp->last == *attr)
+      ipp->last = temp;
+
+    *attr = temp;
+  }
+
+ /*
+  * Return the value element...
+  */
+
+  return (temp->values + element);
+}
+
+
 /*
  * 'ipp_write_file()' - Write IPP data to a file.
  */
@@ -3248,29 +5376,6 @@ ipp_write_file(int         *fd,          /* I - File descriptor */
 }
 
 
-#ifdef __linux
-/*
- * The following symbol definitions are provided only for KDE
- * compatibility during the CUPS 1.2 testing period and will be
- * removed in a future release of CUPS.  These are PRIVATE APIs
- * from CUPS 1.1.x that the KDE developers chose to use...
- */
-
-ipp_attribute_t *                      /* O - New attribute */
-_ipp_add_attr(ipp_t *ipp,              /* I - IPP message */
-              int   num_values)                /* I - Number of values */
-{
-  return (_ippAddAttr(ipp, num_values));
-}
-
-void
-_ipp_free_attr(ipp_attribute_t *attr)  /* I - Attribute to free */
-{
-  _ippFreeAttr(attr);
-}
-#endif /* __linux */
-
-
 /*
- * End of "$Id: ipp.c 7847 2008-08-19 04:22:14Z mike $".
+ * End of "$Id: ipp.c 10102 2011-11-02 23:52:39Z mike $".
  */
index 78e76fcba737af6176c5939099b2d0436cd91665..2f29d59dc035d58408b948b3f17ae9743166badb 100644 (file)
@@ -63,54 +63,14 @@ extern "C" {
  * Types and structures...
  */
 
-typedef enum ipp_tag_e                 /**** Format tags for attributes ****/
+typedef enum ipp_dstate_e              /**** Document states ****/
 {
-  IPP_TAG_ZERO = 0x00,                 /* Zero tag - used for separators */
-  IPP_TAG_OPERATION,                   /* Operation group */
-  IPP_TAG_JOB,                         /* Job group */
-  IPP_TAG_END,                         /* End-of-attributes */
-  IPP_TAG_PRINTER,                     /* Printer group */
-  IPP_TAG_UNSUPPORTED_GROUP,           /* Unsupported attributes group */
-  IPP_TAG_SUBSCRIPTION,                        /* Subscription group */
-  IPP_TAG_EVENT_NOTIFICATION,          /* Event group */
-  IPP_TAG_DOCUMENT = 0x09,             /* Document group */
-  IPP_TAG_UNSUPPORTED_VALUE = 0x10,    /* Unsupported value */
-  IPP_TAG_DEFAULT,                     /* Default value */
-  IPP_TAG_UNKNOWN,                     /* Unknown value */
-  IPP_TAG_NOVALUE,                     /* No-value value */
-  IPP_TAG_NOTSETTABLE = 0x15,          /* Not-settable value */
-  IPP_TAG_DELETEATTR,                  /* Delete-attribute value */
-  IPP_TAG_ADMINDEFINE,                 /* Admin-defined value */
-  IPP_TAG_INTEGER = 0x21,              /* Integer value */
-  IPP_TAG_BOOLEAN,                     /* Boolean value */
-  IPP_TAG_ENUM,                                /* Enumeration value */
-  IPP_TAG_STRING = 0x30,               /* Octet string value */
-  IPP_TAG_DATE,                                /* Date/time value */
-  IPP_TAG_RESOLUTION,                  /* Resolution value */
-  IPP_TAG_RANGE,                       /* Range value */
-  IPP_TAG_BEGIN_COLLECTION,            /* Beginning of collection value */
-  IPP_TAG_TEXTLANG,                    /* Text-with-language value */
-  IPP_TAG_NAMELANG,                    /* Name-with-language value */
-  IPP_TAG_END_COLLECTION,              /* End of collection value */
-  IPP_TAG_TEXT = 0x41,                 /* Text value */
-  IPP_TAG_NAME,                                /* Name value */
-  IPP_TAG_RESERVED_STRING,             /* Reserved for future string value @private@ */
-  IPP_TAG_KEYWORD,                     /* Keyword value */
-  IPP_TAG_URI,                         /* URI value */
-  IPP_TAG_URISCHEME,                   /* URI scheme value */
-  IPP_TAG_CHARSET,                     /* Character set value */
-  IPP_TAG_LANGUAGE,                    /* Language value */
-  IPP_TAG_MIMETYPE,                    /* MIME media type value */
-  IPP_TAG_MEMBERNAME,                  /* Collection member name value */
-  IPP_TAG_MASK = 0x7fffffff,           /* Mask for copied attribute values */
-  IPP_TAG_COPY = -0x7fffffff-1         /* Bitflag for copied attribute values */
-} ipp_tag_t;
-
-typedef enum ipp_res_e                 /**** Resolution units ****/
-{
-  IPP_RES_PER_INCH = 3,                        /* Pixels per inch */
-  IPP_RES_PER_CM                       /* Pixels per centimeter */
-} ipp_res_t;
+  IPP_DOCUMENT_PENDING = 3,
+  IPP_DOCUMENT_PROCESSING = 5,
+  IPP_DOCUMENT_CANCELED = 7,
+  IPP_DOCUMENT_ABORTED,
+  IPP_DOCUMENT_COMPLETED
+} ipp_dstate_t;
 
 typedef enum ipp_finish_e              /**** Finishings ****/
 {
@@ -141,23 +101,19 @@ typedef enum ipp_finish_e         /**** Finishings ****/
   IPP_FINISHINGS_BIND_LEFT = 50,       /* Bind on left */
   IPP_FINISHINGS_BIND_TOP,             /* Bind on top */
   IPP_FINISHINGS_BIND_RIGHT,           /* Bind on right */
-  IPP_FINISHINGS_BIND_BOTTOM           /* Bind on bottom */
+  IPP_FINISHINGS_BIND_BOTTOM,          /* Bind on bottom */
+  IPP_FINISHINGS_TRIM_AFTER_PAGES = 60,        /* Trim output after each page */
+  IPP_FINISHINGS_TRIM_AFTER_DOCUMENTS, /* Trim output after each document */
+  IPP_FINISHINGS_TRIM_AFTER_COPIES,    /* Trim output after each copy */
+  IPP_FINISHINGS_TRIM_AFTER_JOB                /* Trim output after job */
 } ipp_finish_t;
 
-typedef enum ipp_orient_e              /**** Orientation values ****/
+typedef enum ipp_jcollate_e            /**** Job collation types ****/
 {
-  IPP_PORTRAIT = 3,                    /* No rotation */
-  IPP_LANDSCAPE,                       /* 90 degrees counter-clockwise */
-  IPP_REVERSE_LANDSCAPE,               /* 90 degrees clockwise */
-  IPP_REVERSE_PORTRAIT                 /* 180 degrees */
-} ipp_orient_t;
-
-typedef enum ipp_quality_e             /**** Qualities ****/
-{
-  IPP_QUALITY_DRAFT = 3,               /* Draft quality */
-  IPP_QUALITY_NORMAL,                  /* Normal quality */
-  IPP_QUALITY_HIGH                     /* High quality */
-} ipp_quality_t;
+  IPP_JOB_UNCOLLATED_SHEETS = 3,
+  IPP_JOB_COLLATED_DOCUMENTS,
+  IPP_JOB_UNCOLLATED_DOCUMENTS
+} ipp_jcollate_t;
 
 typedef enum ipp_jstate_e              /**** Job states ****/
 {
@@ -168,24 +124,9 @@ typedef enum ipp_jstate_e          /**** Job states ****/
   IPP_JOB_CANCELED,                    /* Job has been canceled */
   IPP_JOB_ABORTED,                     /* Job has aborted due to error */
   IPP_JOB_COMPLETED                    /* Job has completed successfully */
-} ipp_jstate_t;
+  /* Legacy name for canceled state */
 #define IPP_JOB_CANCELLED IPP_JOB_CANCELED
-
-typedef enum ipp_pstate_e              /**** Printer states ****/
-{
-  IPP_PRINTER_IDLE = 3,                        /* Printer is idle */
-  IPP_PRINTER_PROCESSING,              /* Printer is working */
-  IPP_PRINTER_STOPPED                  /* Printer is stopped */
-} ipp_pstate_t;
-
-typedef enum ipp_state_e               /**** IPP states ****/
-{
-  IPP_ERROR = -1,                      /* An error occurred */
-  IPP_IDLE,                            /* Nothing is happening/request completed */
-  IPP_HEADER,                          /* The request header needs to be sent/received */
-  IPP_ATTRIBUTE,                       /* One or more attributes need to be sent/received */
-  IPP_DATA                             /* IPP request data needs to be sent/received */
-} ipp_state_t;
+} ipp_jstate_t;
 
 typedef enum ipp_op_e                  /**** IPP operations ****/
 {
@@ -216,7 +157,10 @@ typedef enum ipp_op_e                      /**** IPP operations ****/
   IPP_CANCEL_SUBSCRIPTION,             /* Cancel a subscription @since CUPS 1.2/Mac OS X 10.5@ */
   IPP_GET_NOTIFICATIONS,               /* Get notification events @since CUPS 1.2/Mac OS X 10.5@ */
   IPP_SEND_NOTIFICATIONS,              /* Send notification events @private@ */
-  IPP_GET_PRINT_SUPPORT_FILES = 0x0021,        /* Get printer support files @private@ */
+  IPP_GET_RESOURCE_ATTRIBUTES,         /* Get resource attributes @private@ */
+  IPP_GET_RESOURCE_DATA,               /* Get resource data @private@ */
+  IPP_GET_RESOURCES,                   /* Get list of resources @private@ */
+  IPP_GET_PRINT_SUPPORT_FILES,         /* Get printer support files @private@ */
   IPP_ENABLE_PRINTER,                  /* Start a printer */
   IPP_DISABLE_PRINTER,                 /* Stop a printer */
   IPP_PAUSE_PRINTER_AFTER_CURRENT_JOB, /* Stop printer after the current job @private@ */
@@ -260,11 +204,48 @@ typedef enum ipp_op_e                     /**** IPP operations ****/
   CUPS_AUTHENTICATE_JOB,               /* Authenticate a job @since CUPS 1.2/Mac OS X 10.5@ */
   CUPS_GET_PPD,                                /* Get a PPD file @since CUPS 1.3/Mac OS X 10.5@ */
   CUPS_GET_DOCUMENT = 0x4027           /* Get a document file @since CUPS 1.4/Mac OS X 10.6@ */
-} ipp_op_t;
 
-/* Old names for the operations */
+  /* Legacy names for the add operations */
 #define CUPS_ADD_PRINTER       CUPS_ADD_MODIFY_PRINTER
 #define CUPS_ADD_CLASS         CUPS_ADD_MODIFY_CLASS
+} ipp_op_t;
+
+typedef enum ipp_orient_e              /**** Orientation values ****/
+{
+  IPP_PORTRAIT = 3,                    /* No rotation */
+  IPP_LANDSCAPE,                       /* 90 degrees counter-clockwise */
+  IPP_REVERSE_LANDSCAPE,               /* 90 degrees clockwise */
+  IPP_REVERSE_PORTRAIT                 /* 180 degrees */
+} ipp_orient_t;
+
+typedef enum ipp_pstate_e              /**** Printer states ****/
+{
+  IPP_PRINTER_IDLE = 3,                        /* Printer is idle */
+  IPP_PRINTER_PROCESSING,              /* Printer is working */
+  IPP_PRINTER_STOPPED                  /* Printer is stopped */
+} ipp_pstate_t;
+
+typedef enum ipp_quality_e             /**** Qualities ****/
+{
+  IPP_QUALITY_DRAFT = 3,               /* Draft quality */
+  IPP_QUALITY_NORMAL,                  /* Normal quality */
+  IPP_QUALITY_HIGH                     /* High quality */
+} ipp_quality_t;
+
+typedef enum ipp_res_e                 /**** Resolution units ****/
+{
+  IPP_RES_PER_INCH = 3,                        /* Pixels per inch */
+  IPP_RES_PER_CM                       /* Pixels per centimeter */
+} ipp_res_t;
+
+typedef enum ipp_state_e               /**** IPP states ****/
+{
+  IPP_ERROR = -1,                      /* An error occurred */
+  IPP_IDLE,                            /* Nothing is happening/request completed */
+  IPP_HEADER,                          /* The request header needs to be sent/received */
+  IPP_ATTRIBUTE,                       /* One or more attributes need to be sent/received */
+  IPP_DATA                             /* IPP request data needs to be sent/received */
+} ipp_state_t;
 
 typedef enum ipp_status_e              /**** IPP status codes ****/
 {
@@ -272,9 +253,9 @@ typedef enum ipp_status_e           /**** IPP status codes ****/
   IPP_OK_SUBST,                                /* successful-ok-ignored-or-substituted-attributes */
   IPP_OK_CONFLICT,                     /* successful-ok-conflicting-attributes */
   IPP_OK_IGNORED_SUBSCRIPTIONS,                /* successful-ok-ignored-subscriptions */
-  IPP_OK_IGNORED_NOTIFICATIONS,                /* successful-ok-ignored-notifications */
+  IPP_OK_IGNORED_NOTIFICATIONS,                /* successful-ok-ignored-notifications @private@ */
   IPP_OK_TOO_MANY_EVENTS,              /* successful-ok-too-many-events */
-  IPP_OK_BUT_CANCEL_SUBSCRIPTION,      /* successful-ok-but-cancel-subscription */
+  IPP_OK_BUT_CANCEL_SUBSCRIPTION,      /* successful-ok-but-cancel-subscription @private@ */
   IPP_OK_EVENTS_COMPLETE,              /* successful-ok-events-complete */
   IPP_REDIRECTION_OTHER_SITE = 0x200,  /* redirection-other-site @private@ */
   CUPS_SEE_OTHER = 0x280,              /* cups-see-other */
@@ -300,8 +281,12 @@ typedef enum ipp_status_e          /**** IPP status codes ****/
   IPP_ATTRIBUTES_NOT_SETTABLE,         /* client-error-attributes-not-settable */
   IPP_IGNORED_ALL_SUBSCRIPTIONS,       /* client-error-ignored-all-subscriptions */
   IPP_TOO_MANY_SUBSCRIPTIONS,          /* client-error-too-many-subscriptions */
-  IPP_IGNORED_ALL_NOTIFICATIONS,       /* client-error-ignored-all-notifications */
-  IPP_PRINT_SUPPORT_FILE_NOT_FOUND,    /* client-error-print-support-file-not-found */
+  IPP_IGNORED_ALL_NOTIFICATIONS,       /* client-error-ignored-all-notifications @private@ */
+  IPP_PRINT_SUPPORT_FILE_NOT_FOUND,    /* client-error-print-support-file-not-found @private@ */
+  IPP_DOCUMENT_PASSWORD_ERROR,         /* client-error-document-password-error */
+  IPP_DOCUMENT_PERMISSION_ERROR,       /* client-error-document-permission-error */
+  IPP_DOCUMENT_SECURITY_ERROR,         /* client-error-document-security-error */
+  IPP_DOCUMENT_UNPRINTABLE_ERROR,      /* client-error-document-unprintable-error */
 
   IPP_INTERNAL_ERROR = 0x0500,         /* server-error-internal-error */
   IPP_OPERATION_NOT_SUPPORTED,         /* server-error-operation-not-supported */
@@ -314,116 +299,75 @@ typedef enum ipp_status_e                /**** IPP status codes ****/
   IPP_ERROR_JOB_CANCELED,              /* server-error-job-canceled */
   IPP_MULTIPLE_JOBS_NOT_SUPPORTED,     /* server-error-multiple-document-jobs-not-supported */
   IPP_PRINTER_IS_DEACTIVATED,          /* server-error-printer-is-deactivated */
+  IPP_TOO_MANY_JOBS,                   /* server-error-too-many-jobs */
+  IPP_TOO_MANY_DOCUMENTS,              /* server-error-too-many-documents */
 
   IPP_AUTHENTICATION_CANCELED = 0x1000,        /* Authentication canceled by user @since CUPS 1.5/Mac OS X 10.7@ */
   IPP_PKI_ERROR,                       /* Error negotiating a secure connection @since CUPS 1.5/Mac OS X 10.7@ */
   IPP_UPGRADE_REQUIRED                 /* TLS upgrade required */
-} ipp_status_t;
-#define IPP_ERROR_JOB_CANCELLED IPP_ERROR_JOB_CANCELED
 
-typedef unsigned char ipp_uchar_t;     /**** Unsigned 8-bit integer/character ****/
-
-/**** New in CUPS 1.2 ****/
-typedef ssize_t        (*ipp_iocb_t)(void *, ipp_uchar_t *, size_t);
-                                       /**** IPP IO Callback Function @since CUPS 1.2/Mac OS X 10.5@ ****/
-
-typedef union ipp_request_u            /**** Request Header ****/
-{
-  struct                               /* Any Header */
-  {
-    ipp_uchar_t        version[2];             /* Protocol version number */
-    int                op_status;              /* Operation ID or status code*/
-    int                request_id;             /* Request ID */
-  }            any;
-
-  struct                               /* Operation Header */
-  {
-    ipp_uchar_t        version[2];             /* Protocol version number */
-    ipp_op_t   operation_id;           /* Operation ID */
-    int                request_id;             /* Request ID */
-  }            op;
-
-  struct                               /* Status Header */
-  {
-    ipp_uchar_t        version[2];             /* Protocol version number */
-    ipp_status_t status_code;          /* Status code */
-    int                request_id;             /* Request ID */
-  }            status;
-
-  /**** New in CUPS 1.1.19 ****/
-  struct                               /* Event Header @since CUPS 1.1.19/Mac OS X 10.3@ */
-  {
-    ipp_uchar_t        version[2];             /* Protocol version number */
-    ipp_status_t status_code;          /* Status code */
-    int                request_id;             /* Request ID */
-  }            event;
-} ipp_request_t;
+  /* Legacy name for canceled status */
+#define IPP_ERROR_JOB_CANCELLED IPP_ERROR_JOB_CANCELED
 
-/**** New in CUPS 1.1.19 ****/
-typedef struct ipp_s ipp_t;
+} ipp_status_t;
 
-typedef union ipp_value_u              /**** Attribute Value ****/
+typedef enum ipp_tag_e                 /**** Format tags for attributes ****/
 {
-  int          integer;                /* Integer/enumerated value */
-
-  char         boolean;                /* Boolean value */
-
-  ipp_uchar_t  date[11];               /* Date/time value */
-
-  struct
-  {
-    int                xres,                   /* Horizontal resolution */
-               yres;                   /* Vertical resolution */
-    ipp_res_t  units;                  /* Resolution units */
-  }            resolution;             /* Resolution value */
-
-  struct
-  {
-    int                lower,                  /* Lower value */
-               upper;                  /* Upper value */
-  }            range;                  /* Range of integers value */
-
-  struct
-  {
-    char       *charset;               /* Character set */
-    char       *text;                  /* String */
-  }            string;                 /* String with language value */
-
-  struct
-  {
-    int                length;                 /* Length of attribute */
-    void       *data;                  /* Data in attribute */
-  }            unknown;                /* Unknown attribute type */
-
-/**** New in CUPS 1.1.19 ****/
-  ipp_t                *collection;            /* Collection value @since CUPS 1.1.19/Mac OS X 10.3@ */
-} ipp_value_t;
+  IPP_TAG_ZERO = 0x00,                 /* Zero tag - used for separators */
+  IPP_TAG_OPERATION,                   /* Operation group */
+  IPP_TAG_JOB,                         /* Job group */
+  IPP_TAG_END,                         /* End-of-attributes */
+  IPP_TAG_PRINTER,                     /* Printer group */
+  IPP_TAG_UNSUPPORTED_GROUP,           /* Unsupported attributes group */
+  IPP_TAG_SUBSCRIPTION,                        /* Subscription group */
+  IPP_TAG_EVENT_NOTIFICATION,          /* Event group */
+  IPP_TAG_RESOURCE,                    /* Resource group @private@ */
+  IPP_TAG_DOCUMENT,                    /* Document group */
+  IPP_TAG_UNSUPPORTED_VALUE = 0x10,    /* Unsupported value */
+  IPP_TAG_DEFAULT,                     /* Default value */
+  IPP_TAG_UNKNOWN,                     /* Unknown value */
+  IPP_TAG_NOVALUE,                     /* No-value value */
+  IPP_TAG_NOTSETTABLE = 0x15,          /* Not-settable value */
+  IPP_TAG_DELETEATTR,                  /* Delete-attribute value */
+  IPP_TAG_ADMINDEFINE,                 /* Admin-defined value */
+  IPP_TAG_INTEGER = 0x21,              /* Integer value */
+  IPP_TAG_BOOLEAN,                     /* Boolean value */
+  IPP_TAG_ENUM,                                /* Enumeration value */
+  IPP_TAG_STRING = 0x30,               /* Octet string value */
+  IPP_TAG_DATE,                                /* Date/time value */
+  IPP_TAG_RESOLUTION,                  /* Resolution value */
+  IPP_TAG_RANGE,                       /* Range value */
+  IPP_TAG_BEGIN_COLLECTION,            /* Beginning of collection value */
+  IPP_TAG_TEXTLANG,                    /* Text-with-language value */
+  IPP_TAG_NAMELANG,                    /* Name-with-language value */
+  IPP_TAG_END_COLLECTION,              /* End of collection value */
+  IPP_TAG_TEXT = 0x41,                 /* Text value */
+  IPP_TAG_NAME,                                /* Name value */
+  IPP_TAG_RESERVED_STRING,             /* Reserved for future string value @private@ */
+  IPP_TAG_KEYWORD,                     /* Keyword value */
+  IPP_TAG_URI,                         /* URI value */
+  IPP_TAG_URISCHEME,                   /* URI scheme value */
+  IPP_TAG_CHARSET,                     /* Character set value */
+  IPP_TAG_LANGUAGE,                    /* Language value */
+  IPP_TAG_MIMETYPE,                    /* MIME media type value */
+  IPP_TAG_MEMBERNAME,                  /* Collection member name value */
+  IPP_TAG_EXTENSION = 0x7f,            /* Extension point for 32-bit tags */
+  IPP_TAG_MASK = 0x7fffffff,           /* Mask for copied attribute values @private@ */
+  /* The following expression is used to avoid compiler warnings with +/-0x80000000 */
+  IPP_TAG_COPY = -0x7fffffff-1         /* Bitflag for copied attribute values @private@ */
+} ipp_tag_t;
 
-typedef struct ipp_attribute_s         /**** Attribute ****/
-{
-  struct ipp_attribute_s *next;                /* Next attribute in list */
-  ipp_tag_t    group_tag,              /* Job/Printer/Operation group tag */
-               value_tag;              /* What type of value is it? */
-  char         *name;                  /* Name of attribute */
-  int          num_values;             /* Number of values */
-  ipp_value_t  values[1];              /* Values */
-} ipp_attribute_t;
-
-struct ipp_s                           /**** IPP Request/Response/Notification ****/
-{
-  ipp_state_t  state;                  /* State of request */
-  ipp_request_t        request;                /* Request header */
-  ipp_attribute_t *attrs;              /* Attributes */
-  ipp_attribute_t *last;               /* Last attribute in list */
-  ipp_attribute_t *current;            /* Current attribute (for read/write) */
-  ipp_tag_t    curtag;                 /* Current attribute group tag */
+typedef unsigned char ipp_uchar_t;     /**** Unsigned 8-bit integer/character ****/
+typedef struct _ipp_s ipp_t;           /**** IPP request/response data ****/
+typedef struct _ipp_attribute_s ipp_attribute_t;
+                                       /**** IPP attribute ****/
 
 /**** New in CUPS 1.2 ****/
-  ipp_attribute_t *prev;               /* Previous attribute (for read) @since CUPS 1.2/Mac OS X 10.5@ */
+typedef ssize_t        (*ipp_iocb_t)(void *context, ipp_uchar_t *buffer, size_t bytes);
+                                       /**** IPP IO Callback Function @since CUPS 1.2/Mac OS X 10.5@ ****/
 
-/**** New in CUPS 1.4.4 ****/
-  int          use;                    /* Use count @since CUPS 1.4.4/Mac OS X 10.6.?@ */
-};
+/**** New in CUPS 1.6 ****/
+typedef int (*ipp_copycb_t)(void *context, ipp_t *dst, ipp_attribute_t *attr);
 
 
 /*
@@ -438,10 +382,10 @@ extern ipp_attribute_t    *ippAddBooleans(ipp_t *ipp, ipp_tag_t group,
 extern ipp_attribute_t *ippAddDate(ipp_t *ipp, ipp_tag_t group,
                                    const char *name, const ipp_uchar_t *value);
 extern ipp_attribute_t *ippAddInteger(ipp_t *ipp, ipp_tag_t group,
-                                      ipp_tag_t type, const char *name,
+                                      ipp_tag_t value_tag, const char *name,
                                       int value);
 extern ipp_attribute_t *ippAddIntegers(ipp_t *ipp, ipp_tag_t group,
-                                       ipp_tag_t type, const char *name,
+                                       ipp_tag_t value_tag, const char *name,
                                        int num_values, const int *values);
 extern ipp_attribute_t *ippAddRange(ipp_t *ipp, ipp_tag_t group,
                                     const char *name, int lower, int upper);
@@ -457,19 +401,19 @@ extern ipp_attribute_t    *ippAddResolutions(ipp_t *ipp, ipp_tag_t group,
                                           const int *yres);
 extern ipp_attribute_t *ippAddSeparator(ipp_t *ipp);
 extern ipp_attribute_t *ippAddString(ipp_t *ipp, ipp_tag_t group,
-                                     ipp_tag_t type, const char *name,
-                                     const char *charset, const char *value);
+                                     ipp_tag_t value_tag, const char *name,
+                                     const char *language, const char *value);
 extern ipp_attribute_t *ippAddStrings(ipp_t *ipp, ipp_tag_t group,
-                                      ipp_tag_t type, const char *name,
-                                      int num_values, const char *charset,
+                                      ipp_tag_t value_tag, const char *name,
+                                      int num_values, const char *language,
                                       const char * const *values);
 extern time_t          ippDateToTime(const ipp_uchar_t *date);
 extern void            ippDelete(ipp_t *ipp);
 extern const char      *ippErrorString(ipp_status_t error);
 extern ipp_attribute_t *ippFindAttribute(ipp_t *ipp, const char *name,
-                                         ipp_tag_t type);
+                                         ipp_tag_t value_tag);
 extern ipp_attribute_t *ippFindNextAttribute(ipp_t *ipp, const char *name,
-                                             ipp_tag_t type);
+                                             ipp_tag_t value_tag);
 extern size_t          ippLength(ipp_t *ipp);
 extern ipp_t           *ippNew(void);
 extern ipp_state_t     ippRead(http_t *http, ipp_t *ipp);
@@ -488,7 +432,7 @@ extern void         ippDeleteAttribute(ipp_t *ipp, ipp_attribute_t *attr) _CUPS_API_1_1
 extern ipp_state_t     ippReadFile(int fd, ipp_t *ipp) _CUPS_API_1_1_19;
 extern ipp_state_t     ippWriteFile(int fd, ipp_t *ipp) _CUPS_API_1_1_19;
 
-/**** New in CUPS 1.2 ****/
+/**** New in CUPS 1.2/Mac OS X 10.5 ****/
 extern ipp_attribute_t *ippAddOctetString(ipp_t *ipp, ipp_tag_t group,
                                           const char *name,
                                           const void *data, int datalen) _CUPS_API_1_2;
@@ -501,10 +445,70 @@ extern ipp_state_t        ippReadIO(void *src, ipp_iocb_t cb, int blocking,
 extern ipp_state_t     ippWriteIO(void *dst, ipp_iocb_t cb, int blocking,
                                   ipp_t *parent, ipp_t *ipp) _CUPS_API_1_2;
 
-/**** New in CUPS 1.4 ****/
+/**** New in CUPS 1.4/Mac OS X 10.6 ****/
 extern const char      *ippTagString(ipp_tag_t tag) _CUPS_API_1_4;
 extern ipp_tag_t       ippTagValue(const char *name) _CUPS_API_1_4;
 
+/**** New in CUPS 1.6 ****/
+extern ipp_attribute_t *ippAddOutOfBand(ipp_t *ipp, ipp_tag_t group, ipp_tag_t value_tag,
+                                        const char *name);
+extern size_t          ippAttributeString(ipp_attribute_t *attr, char *buffer,
+                                          size_t bufsize) _CUPS_API_1_6;
+extern ipp_attribute_t *ippCopyAttribute(ipp_t *dst, ipp_attribute_t *attr,
+                                        int quickcopy) _CUPS_API_1_6;
+extern int             ippCopyAttributes(ipp_t *dst, ipp_t *src,
+                                         int quickcopy, ipp_copycb_t cb, void *context)
+                                         _CUPS_API_1_6;
+extern int             ippDeleteValues(ipp_t *ipp, ipp_attribute_t *attr, int element,
+                                       int count) _CUPS_API_1_6;
+extern const char      *ippEnumString(const char *attrname, int enumvalue) _CUPS_API_1_6;
+extern int             ippEnumValue(const char *attrname, const char *enumstring)
+                                    _CUPS_API_1_6;
+extern ipp_attribute_t *ippFirstAttribute(ipp_t *ipp) _CUPS_API_1_6;
+extern int             ippGetBoolean(ipp_attribute_t *attr, int element)
+                                     _CUPS_API_1_6;
+extern ipp_t           *ippGetCollection(ipp_attribute_t *attr,
+                                         int element) _CUPS_API_1_6;
+extern int             ippGetCount(ipp_attribute_t *attr) _CUPS_API_1_6;
+extern ipp_tag_t       ippGetGroupTag(ipp_attribute_t *attr) _CUPS_API_1_6;
+extern int             ippGetInteger(ipp_attribute_t *attr, int element)
+                                     _CUPS_API_1_6;
+extern const char      *ippGetName(ipp_attribute_t *attr) _CUPS_API_1_6;
+extern ipp_op_t                ippGetOperation(ipp_t *ipp) _CUPS_API_1_6;
+extern int             ippGetRequestId(ipp_t *ipp) _CUPS_API_1_6;
+extern int             ippGetResolution(ipp_attribute_t *attr, int element,
+                                        int *yres, ipp_res_t *units) _CUPS_API_1_6;
+extern ipp_status_t    ippGetStatusCode(ipp_t *ipp) _CUPS_API_1_6;
+extern const char      *ippGetString(ipp_attribute_t *attr, int element,
+                                     const char **language) _CUPS_API_1_6;
+extern ipp_tag_t       ippGetValueTag(ipp_attribute_t *attr) _CUPS_API_1_6;
+extern int             ippGetVersion(ipp_t *ipp, int *minor) _CUPS_API_1_6;
+extern ipp_attribute_t *ippNextAttribute(ipp_t *ipp) _CUPS_API_1_6;
+extern int             ippSetBoolean(ipp_t *ipp, ipp_attribute_t **attr,
+                                     int element, int boolvalue) _CUPS_API_1_6;
+extern int             ippSetCollection(ipp_t *ipp, ipp_attribute_t **attr,
+                                        int element, ipp_t *colvalue) _CUPS_API_1_6;
+extern int             ippSetGroupTag(ipp_t *ipp, ipp_attribute_t **attr,
+                                      ipp_tag_t group_tag) _CUPS_API_1_6;
+extern int             ippSetInteger(ipp_t *ipp, ipp_attribute_t **attr,
+                                     int element, int intvalue) _CUPS_API_1_6;
+extern int             ippSetName(ipp_t *ipp, ipp_attribute_t **attr, const char *name)
+                                  _CUPS_API_1_6;
+extern int             ippSetOperation(ipp_t *ipp, ipp_op_t op) _CUPS_API_1_6;
+extern int             ippSetRange(ipp_t *ipp, ipp_attribute_t **attr, int element,
+                                   int lowervalue, int uppervalue) _CUPS_API_1_6;
+extern int             ippSetRequestId(ipp_t *ipp, int request_id)
+                                       _CUPS_API_1_6;
+extern int             ippSetResolution(ipp_t *ipp, ipp_attribute_t **attr,
+                                        int element, ipp_res_t unitsvalue,
+                                        int xresvalue, int yresvalue) _CUPS_API_1_6;
+extern int             ippSetStatusCode(ipp_t *ipp, ipp_status_t status) _CUPS_API_1_6;
+extern int             ippSetString(ipp_t *ipp, ipp_attribute_t **attr,
+                                    int element, const char *strvalue) _CUPS_API_1_6;
+extern int             ippSetValueTag(ipp_t *ipp, ipp_attribute_t **attr,
+                                      ipp_tag_t value_tag) _CUPS_API_1_6;
+extern int             ippSetVersion(ipp_t *ipp, int major, int minor) _CUPS_API_1_6;
+
 
 /*
  * C++ magic...
index 46808ed920bd7a9fb173136e4fe3e1998a165e0b..e0188c6cbda73fe6fbf391eb5def54b36c2e70dd 100644 (file)
@@ -80,7 +80,7 @@ static const char * const lang_encodings[] =
                          "cp1256",             "cp1257",
                          "cp1258",             "koi8-r",
                          "koi8-u",             "iso-8859-11",
-                         "iso-8859-16",        "mac-roman",
+                         "iso-8859-16",        "mac",
                          "unknown",            "unknown",
                          "unknown",            "unknown",
                          "unknown",            "unknown",
index 4d095537a0118a9b3a28f9b7b284449f2d81e1b9..f500e771207c4ca568ce80da7eb298315cf7d699 100644 (file)
@@ -50,9 +50,7 @@ _httpPeek
 _httpResolveURI
 _httpSetTimeout
 _httpWait
-_ippAddAttr
 _ippFindOption
-_ippFreeAttr
 _ppdFreeLanguages
 _ppdGetEncoding
 _ppdGetLanguages
index e161d057a440f6d594093b682696997d885104d7..c402148237338e8131840ffe4a34cf74746c073b 100644 (file)
@@ -1271,7 +1271,8 @@ _ppdCacheCreateWithPPD(ppd_file_t *ppd)   /* I - PPD file */
 
     if (filter)
       cupsArrayAdd(pc->filters,
-                   "application/vnd.cups-command application/postscript 0 -");
+                   "application/vnd.cups-command application/postscript 100 "
+                   "commandtops");
   }
 
   if ((ppd_attr = ppdFindAttr(ppd, "cupsPreFilter", NULL)) != NULL)
index f66036f9ae310b8bd742c2acb63762fcd4953cbc..276b47bd5b2ca30589fd3fcc8169513d20a845ee 100644 (file)
@@ -3,6 +3,10 @@
  *
  *   PostScript Printer Description definitions for CUPS.
  *
+ *   THESE APIS ARE DEPRECATED. TO COMPILE WITHOUT WARNINGS ADD
+ *   "-D_PPD_DEPRECATED" TO YOUR COMPILE OPTIONS.  THIS HEADER AND THESE
+ *   FUNCTIONS WILL BE REMOVED IN A FUTURE RELEASE OF CUPS.
+ *
  *   Copyright 2007-2011 by Apple Inc.
  *   Copyright 1997-2007 by Easy Software Products, all rights reserved.
  *
@@ -46,6 +50,16 @@ extern "C" {
 #  endif /* __cplusplus */
 
 
+/*
+ * Define _PPD_DEPRECATED to silence the warnings about PPD functions being
+ * deprecated...
+ */
+
+#  ifndef _PPD_DEPRECATED
+#    define _PPD_DEPRECATED _CUPS_DEPRECATED
+#  endif /* !_PPD_DEPRECATED */
+
+
 /*
  * PPD version...
  */
@@ -361,7 +375,8 @@ extern int          ppdEmitFd(ppd_file_t *ppd, int fd,
 extern int             ppdEmitJCL(ppd_file_t *ppd, FILE *fp, int job_id,
                                   const char *user, const char *title);
 extern ppd_choice_t    *ppdFindChoice(ppd_option_t *o, const char *option);
-extern ppd_choice_t    *ppdFindMarkedChoice(ppd_file_t *ppd, const char *keyword);
+extern ppd_choice_t    *ppdFindMarkedChoice(ppd_file_t *ppd,
+                                            const char *keyword);
 extern ppd_option_t    *ppdFindOption(ppd_file_t *ppd, const char *keyword);
 extern int             ppdIsMarked(ppd_file_t *ppd, const char *keyword,
                                    const char *option);
@@ -376,64 +391,67 @@ extern ppd_size_t *ppdPageSize(ppd_file_t *ppd, const char *name);
 extern float           ppdPageWidth(ppd_file_t *ppd, const char *name);
 
 /**** New in CUPS 1.1.19 ****/
-extern const char      *ppdErrorString(ppd_status_t status) _CUPS_API_1_1_19;
+extern const char      *ppdErrorString(ppd_status_t status) _PPD_DEPRECATED;
 extern ppd_attr_t      *ppdFindAttr(ppd_file_t *ppd, const char *name,
-                                    const char *spec) _CUPS_API_1_1_19;
+                                    const char *spec) _PPD_DEPRECATED;
 extern ppd_attr_t      *ppdFindNextAttr(ppd_file_t *ppd, const char *name,
-                                        const char *spec) _CUPS_API_1_1_19;
-extern ppd_status_t    ppdLastError(int *line) _CUPS_API_1_1_19;
+                                        const char *spec) _PPD_DEPRECATED;
+extern ppd_status_t    ppdLastError(int *line) _PPD_DEPRECATED;
 
 /**** New in CUPS 1.1.20 ****/
-extern void            ppdSetConformance(ppd_conform_t c) _CUPS_API_1_1_20;
+extern void            ppdSetConformance(ppd_conform_t c) _PPD_DEPRECATED;
 
 /**** New in CUPS 1.2 ****/
 extern int             ppdCollect2(ppd_file_t *ppd, ppd_section_t section,
-                                   float min_order, ppd_choice_t  ***choices) _CUPS_API_1_2;
+                                   float min_order, ppd_choice_t  ***choices)
+                                   _PPD_DEPRECATED;
 extern int             ppdEmitAfterOrder(ppd_file_t *ppd, FILE *fp,
                                          ppd_section_t section, int limit,
-                                         float min_order) _CUPS_API_1_2;
-extern int             ppdEmitJCLEnd(ppd_file_t *ppd, FILE *fp) _CUPS_API_1_2;
+                                         float min_order) _PPD_DEPRECATED;
+extern int             ppdEmitJCLEnd(ppd_file_t *ppd, FILE *fp) _PPD_DEPRECATED;
 extern char            *ppdEmitString(ppd_file_t *ppd, ppd_section_t section,
-                                      float min_order) _CUPS_API_1_2;
+                                      float min_order) _PPD_DEPRECATED;
 extern ppd_coption_t   *ppdFindCustomOption(ppd_file_t *ppd,
-                                            const char *keyword) _CUPS_API_1_2;
+                                            const char *keyword) _PPD_DEPRECATED;
 extern ppd_cparam_t    *ppdFindCustomParam(ppd_coption_t *opt,
-                                           const char *name) _CUPS_API_1_2;
-extern ppd_cparam_t    *ppdFirstCustomParam(ppd_coption_t *opt) _CUPS_API_1_2;
-extern ppd_option_t    *ppdFirstOption(ppd_file_t *ppd) _CUPS_API_1_2;
-extern ppd_cparam_t    *ppdNextCustomParam(ppd_coption_t *opt) _CUPS_API_1_2;
-extern ppd_option_t    *ppdNextOption(ppd_file_t *ppd) _CUPS_API_1_2;
-extern int             ppdLocalize(ppd_file_t *ppd) _CUPS_API_1_2;
-extern ppd_file_t      *ppdOpen2(cups_file_t *fp) _CUPS_API_1_2;
+                                           const char *name) _PPD_DEPRECATED;
+extern ppd_cparam_t    *ppdFirstCustomParam(ppd_coption_t *opt) _PPD_DEPRECATED;
+extern ppd_option_t    *ppdFirstOption(ppd_file_t *ppd) _PPD_DEPRECATED;
+extern ppd_cparam_t    *ppdNextCustomParam(ppd_coption_t *opt) _PPD_DEPRECATED;
+extern ppd_option_t    *ppdNextOption(ppd_file_t *ppd) _PPD_DEPRECATED;
+extern int             ppdLocalize(ppd_file_t *ppd) _PPD_DEPRECATED;
+extern ppd_file_t      *ppdOpen2(cups_file_t *fp) _PPD_DEPRECATED;
 
 /**** New in CUPS 1.3/Mac OS X 10.5 ****/
 extern const char      *ppdLocalizeIPPReason(ppd_file_t *ppd,
                                              const char *reason,
                                              const char *scheme,
                                              char *buffer,
-                                             size_t bufsize) _CUPS_API_1_3;
+                                             size_t bufsize) _PPD_DEPRECATED;
 
 /**** New in CUPS 1.4/Mac OS X 10.6 ****/
 extern int             cupsGetConflicts(ppd_file_t *ppd, const char *option,
                                         const char *choice,
                                         cups_option_t **options)
-                                            _CUPS_API_1_4;
-extern int             cupsResolveConflicts(ppd_file_t *ppd, const char *option,
+                                            _PPD_DEPRECATED;
+extern int             cupsResolveConflicts(ppd_file_t *ppd,
+                                            const char *option,
                                             const char *choice,
                                             int *num_options,
                                             cups_option_t **options)
-                                            _CUPS_API_1_4;
+                                            _PPD_DEPRECATED;
 extern int             ppdInstallableConflict(ppd_file_t *ppd,
                                               const char *option,
                                               const char *choice)
-                                                  _CUPS_API_1_4;
+                                                  _PPD_DEPRECATED;
 extern ppd_attr_t      *ppdLocalizeAttr(ppd_file_t *ppd, const char *keyword,
-                                        const char *spec) _CUPS_API_1_4;
+                                        const char *spec) _PPD_DEPRECATED;
 extern const char      *ppdLocalizeMarkerName(ppd_file_t *ppd,
-                                              const char *name) _CUPS_API_1_4;
+                                              const char *name)
+                                              _PPD_DEPRECATED;
 extern int             ppdPageSizeLimits(ppd_file_t *ppd,
                                          ppd_size_t *minimum,
-                                         ppd_size_t *maximum) _CUPS_API_1_4;
+                                         ppd_size_t *maximum) _PPD_DEPRECATED;
 
 
 /*
index 5c7ca2397113db213d1118686b4278158768e200..7cc55b44bed1f52c1721c0f3504d252f502ddb3d 100644 (file)
@@ -103,8 +103,8 @@ static _pwg_media_t const cups_pwg_media[] =
   _PWG_MEDIA_IN("na_eur-edp_12x14in", NULL, NULL, 12, 14),
   _PWG_MEDIA_IN("na_arch-b_12x18in", "arch-b", "ARCHB", 12, 18),
   _PWG_MEDIA_IN("na_12x19_12x19in", NULL, "12x19", 12, 19),
-  _PWG_MEDIA_IN("na_b-plus_12x19.17in", NULL, NULL, 12, 19.17),
-  _PWG_MEDIA_IN("na_super-b_13x19in", "super-b", "SuperB", 13, 19),
+  _PWG_MEDIA_IN("na_b-plus_12x19.17in", NULL, "SuperB", 12, 19.17),
+  _PWG_MEDIA_IN("na_super-b_13x19in", "super-b", "13x19", 13, 19),
   _PWG_MEDIA_IN("na_c_17x22in", "c", "AnsiC", 17, 22),
   _PWG_MEDIA_IN("na_arch-c_18x24in", "arch-c", "ARCHC", 18, 24),
   _PWG_MEDIA_IN("na_d_22x34in", "d", "AnsiD", 22, 34),
index efe2174f122c9e5f0d2097b0bac89cea5e733dec..70c83bf4b5e36079b712b16a93a803dbda6d4e72 100644 (file)
@@ -758,7 +758,7 @@ print_attributes(ipp_t *ipp,                /* I - IPP request */
   int                  i;              /* Looping var */
   ipp_tag_t            group;          /* Current group */
   ipp_attribute_t      *attr;          /* Current attribute */
-  ipp_value_t          *val;           /* Current value */
+  _ipp_value_t         *val;           /* Current value */
   static const char * const tags[] =   /* Value/group tag strings */
                        {
                          "reserved-00",
index 719483dd71569fdc50bab8d93d1b030f8ec721a0..6881ec79ddef38b63176b4befd5fb25b3f139dd2 100644 (file)
  * a warning at compile-time.
  */
 
-#  if defined(__GNUC__) && __GNUC__ > 2
+#  if defined(__GNUC__) && __GNUC__ > 2 && !defined(_CUPS_SOURCE)
 #    define _CUPS_DEPRECATED __attribute__ ((__deprecated__))
 #  else
 #    define _CUPS_DEPRECATED
-#  endif /* __GNUC__ && __GNUC__ > 2 */
+#  endif /* __GNUC__ && __GNUC__ > 2 && !_CUPS_SOURCE */
 
 #  ifndef __GNUC__
 #    define __attribute__(x)
index d540b8ed3d85e0fbb8f8218903dab9c21099478d..b0f94ecba6a82a152401e9ecbd23ab5206ce8cf0 100644 (file)
@@ -448,9 +448,11 @@ address records for the specified name.">httpGetHostByName</a></li>
 content-length or transfer-encoding fields.">httpGetLength</a></li>
        <li><a href="#httpGetLength2" title="Get the amount of data remaining from the
 content-length or transfer-encoding fields.">httpGetLength2</a></li>
+       <li><a href="#httpGetState" title="Get the current state of the HTTP request.">httpGetState</a></li>
        <li><a href="#httpGetStatus" title="Get the status of the last HTTP request.">httpGetStatus</a></li>
        <li><a href="#httpGetSubField" title="Get a sub-field value.">httpGetSubField</a></li>
        <li><a href="#httpGetSubField2" title="Get a sub-field value.">httpGetSubField2</a></li>
+       <li><a href="#httpGetVersion" title="Get the HTTP version at the other end.">httpGetVersion</a></li>
        <li><a href="#httpGets" title="Get a line of text from a HTTP connection.">httpGets</a></li>
        <li><a href="#httpHead" title="Send a HEAD request to the server.">httpHead</a></li>
        <li><a href="#httpInitialize" title="Initialize the HTTP interface library and set the
@@ -494,6 +496,7 @@ connection.">httpSetCredentials</a></li>
        <li><a href="#ippAddInteger" title="Add a integer attribute to an IPP message.">ippAddInteger</a></li>
        <li><a href="#ippAddIntegers" title="Add an array of integer values.">ippAddIntegers</a></li>
        <li><a href="#ippAddOctetString" title="Add an octetString value to an IPP message.">ippAddOctetString</a></li>
+       <li><a href="#ippAddOutOfBand" title="Add an out-of-band value to an IPP message.">ippAddOutOfBand</a></li>
        <li><a href="#ippAddRange" title="Add a range of values to an IPP message.">ippAddRange</a></li>
        <li><a href="#ippAddRanges" title="Add ranges of values to an IPP message.">ippAddRanges</a></li>
        <li><a href="#ippAddResolution" title="Add a resolution value to an IPP message.">ippAddResolution</a></li>
@@ -501,24 +504,58 @@ connection.">httpSetCredentials</a></li>
        <li><a href="#ippAddSeparator" title="Add a group separator to an IPP message.">ippAddSeparator</a></li>
        <li><a href="#ippAddString" title="Add a language-encoded string to an IPP message.">ippAddString</a></li>
        <li><a href="#ippAddStrings" title="Add language-encoded strings to an IPP message.">ippAddStrings</a></li>
+       <li><a href="#ippAttributeString" title="Convert the attribute's value to a string.">ippAttributeString</a></li>
+       <li><a href="#ippCopyAttribute" title="Copy an attribute.">ippCopyAttribute</a></li>
+       <li><a href="#ippCopyAttributes" title="Copy attributes from one IPP message to another.">ippCopyAttributes</a></li>
        <li><a href="#ippDateToTime" title="Convert from RFC 1903 Date/Time format to UNIX time
 in seconds.">ippDateToTime</a></li>
        <li><a href="#ippDelete" title="Delete an IPP message.">ippDelete</a></li>
        <li><a href="#ippDeleteAttribute" title="Delete a single attribute in an IPP message.">ippDeleteAttribute</a></li>
+       <li><a href="#ippDeleteValues" title="Delete values in an attribute.">ippDeleteValues</a></li>
+       <li><a href="#ippEnumString" title="Return a string corresponding to the enum value.">ippEnumString</a></li>
+       <li><a href="#ippEnumValue" title="Return the value associated with a given enum string.">ippEnumValue</a></li>
        <li><a href="#ippErrorString" title="Return a name for the given status code.">ippErrorString</a></li>
        <li><a href="#ippErrorValue" title="Return a status code for the given name.">ippErrorValue</a></li>
        <li><a href="#ippFindAttribute" title="Find a named attribute in a request...">ippFindAttribute</a></li>
        <li><a href="#ippFindNextAttribute" title="Find the next named attribute in a request...">ippFindNextAttribute</a></li>
+       <li><a href="#ippFirstAttribute" title="Return the first attribute in the message.">ippFirstAttribute</a></li>
+       <li><a href="#ippGetBoolean" title="Get a boolean value for an attribute.">ippGetBoolean</a></li>
+       <li><a href="#ippGetCollection" title="Get a collection value for an attribute.">ippGetCollection</a></li>
+       <li><a href="#ippGetCount" title="Get the number of values in an attribute.">ippGetCount</a></li>
+       <li><a href="#ippGetGroupTag" title="Get the group associated with an attribute.">ippGetGroupTag</a></li>
+       <li><a href="#ippGetInteger" title="Get the integer/enum value for an attribute.">ippGetInteger</a></li>
+       <li><a href="#ippGetName" title="Get the attribute name.">ippGetName</a></li>
+       <li><a href="#ippGetOperation" title="Get the operation ID in an IPP message.">ippGetOperation</a></li>
+       <li><a href="#ippGetRequestId" title="Get the request ID from an IPP message.">ippGetRequestId</a></li>
+       <li><a href="#ippGetResolution" title="Get a resolution value for an attribute.">ippGetResolution</a></li>
+       <li><a href="#ippGetStatusCode" title="Get the status code from an IPP response or event message.">ippGetStatusCode</a></li>
+       <li><a href="#ippGetString" title="Return the value...">ippGetString</a></li>
+       <li><a href="#ippGetValueTag" title="Get the value tag for an attribute.">ippGetValueTag</a></li>
+       <li><a href="#ippGetVersion" title="Get the major and minor version number from an IPP message.">ippGetVersion</a></li>
        <li><a href="#ippLength" title="Compute the length of an IPP message.">ippLength</a></li>
        <li><a href="#ippNew" title="Allocate a new IPP message.">ippNew</a></li>
        <li><a href="#ippNewRequest" title="Allocate a new IPP request message.">ippNewRequest</a></li>
+       <li><a href="#ippNextAttribute" title="Return the next attribute in the message.">ippNextAttribute</a></li>
        <li><a href="#ippOpString" title="Return a name for the given operation id.">ippOpString</a></li>
        <li><a href="#ippOpValue" title="Return an operation id for the given name.">ippOpValue</a></li>
        <li><a href="#ippPort" title="Return the default IPP port number.">ippPort</a></li>
        <li><a href="#ippRead" title="Read data for an IPP message from a HTTP connection.">ippRead</a></li>
        <li><a href="#ippReadFile" title="Read data for an IPP message from a file.">ippReadFile</a></li>
        <li><a href="#ippReadIO" title="Read data for an IPP message.">ippReadIO</a></li>
+       <li><a href="#ippSetBoolean" title="Set a boolean value in an attribute.">ippSetBoolean</a></li>
+       <li><a href="#ippSetCollection" title="Set a collection value in an attribute.">ippSetCollection</a></li>
+       <li><a href="#ippSetGroupTag" title="Set the group tag of an attribute.">ippSetGroupTag</a></li>
+       <li><a href="#ippSetInteger" title="Set an integer or enum value in an attribute.">ippSetInteger</a></li>
+       <li><a href="#ippSetName" title="Set the name of an attribute.">ippSetName</a></li>
+       <li><a href="#ippSetOperation" title="Set the operation ID in an IPP request message.">ippSetOperation</a></li>
        <li><a href="#ippSetPort" title="Set the default port number.">ippSetPort</a></li>
+       <li><a href="#ippSetRange" title="Set a rangeOfInteger value in an attribute.">ippSetRange</a></li>
+       <li><a href="#ippSetRequestId" title="Set the request ID in an IPP message.">ippSetRequestId</a></li>
+       <li><a href="#ippSetResolution" title="Set a resolution value in an attribute.">ippSetResolution</a></li>
+       <li><a href="#ippSetStatusCode" title="Set the status code in an IPP response or event message.">ippSetStatusCode</a></li>
+       <li><a href="#ippSetString" title="Set a string value in an attribute.">ippSetString</a></li>
+       <li><a href="#ippSetValueTag" title="Set the value tag of an attribute.">ippSetValueTag</a></li>
+       <li><a href="#ippSetVersion" title="Set the version number in an IPP message.">ippSetVersion</a></li>
        <li><a href="#ippTagString" title="Return the tag name corresponding to a tag value.">ippTagString</a></li>
        <li><a href="#ippTagValue" title="Return the tag value corresponding to a tag name.">ippTagValue</a></li>
        <li><a href="#ippTimeToDate" title="Convert from UNIX time to RFC 1903 format.">ippTimeToDate</a></li>
@@ -550,21 +587,19 @@ are server-oriented...">http_state_t</a></li>
        <li><a href="#http_uri_coding_t" title="URI en/decode flags">http_uri_coding_t</a></li>
        <li><a href="#http_uri_status_t" title="URI separation status ">http_uri_status_t</a></li>
        <li><a href="#http_version_t" title="HTTP version numbers">http_version_t</a></li>
-       <li><a href="#ipp_attribute_t" title="Attribute">ipp_attribute_t</a></li>
+       <li><a href="#ipp_attribute_t" title="IPP attribute">ipp_attribute_t</a></li>
+       <li><a href="#ipp_copycb_t" title="Prototypes...">ipp_copycb_t</a></li>
+       <li><a href="#ipp_dstate_t" title="Document states">ipp_dstate_t</a></li>
        <li><a href="#ipp_finish_t" title="Finishings">ipp_finish_t</a></li>
        <li><a href="#ipp_iocb_t" title="IPP IO Callback Function ">ipp_iocb_t</a></li>
-       <li><a href="#ipp_jstate_t" title="Job states">ipp_jstate_t</a></li>
-       <li><a href="#ipp_op_t" title="IPP operations">ipp_op_t</a></li>
+       <li><a href="#ipp_jcollate_t" title="Job collation types">ipp_jcollate_t</a></li>
        <li><a href="#ipp_orient_t" title="Orientation values">ipp_orient_t</a></li>
        <li><a href="#ipp_pstate_t" title="Printer states">ipp_pstate_t</a></li>
        <li><a href="#ipp_quality_t" title="Qualities">ipp_quality_t</a></li>
-       <li><a href="#ipp_request_t" title="Request Header">ipp_request_t</a></li>
        <li><a href="#ipp_res_t" title="Resolution units">ipp_res_t</a></li>
        <li><a href="#ipp_state_t" title="IPP states">ipp_state_t</a></li>
-       <li><a href="#ipp_t" title="Attribute Value">ipp_t</a></li>
-       <li><a href="#ipp_uchar_t" title="IPP status codes">ipp_uchar_t</a></li>
-       <li><a href="#ipp_tag_t" title="Format tags for attributes">ipp_tag_t</a></li>
-       <li><a href="#ipp_value_t" title="Attribute Value">ipp_value_t</a></li>
+       <li><a href="#ipp_t" title="IPP request/response data">ipp_t</a></li>
+       <li><a href="#ipp_uchar_t" title="Unsigned 8-bit integer/character">ipp_uchar_t</a></li>
 </ul></li>
 <li><a href="#STRUCTURES">Structures</a><ul class="code">
        <li><a href="#gss_auth_identity" title="Local functions...">gss_auth_identity</a></li>
@@ -573,12 +608,6 @@ used to enumerate all of the
 addresses that are associated
 with a hostname. ">http_addrlist_s</a></li>
        <li><a href="#http_credential_s" title="HTTP credential data ">http_credential_s</a></li>
-       <li><a href="#ipp_attribute_s" title="Attribute">ipp_attribute_s</a></li>
-       <li><a href="#ipp_s" title="IPP Request/Response/Notification">ipp_s</a></li>
-</ul></li>
-<li><a href="#UNIONS">Unions</a><ul class="code">
-       <li><a href="#ipp_request_u" title="Request Header">ipp_request_u</a></li>
-       <li><a href="#ipp_value_u" title="Attribute Value">ipp_value_u</a></li>
 </ul></li>
 <li><a href="#ENUMERATIONS">Constants</a><ul class="code">
        <li><a href="#http_auth_e" title="HTTP authentication types">http_auth_e</a></li>
@@ -592,7 +621,9 @@ are server-oriented...">http_state_e</a></li>
        <li><a href="#http_uri_coding_e" title="URI en/decode flags">http_uri_coding_e</a></li>
        <li><a href="#http_uri_status_e" title="URI separation status ">http_uri_status_e</a></li>
        <li><a href="#http_version_e" title="HTTP version numbers">http_version_e</a></li>
+       <li><a href="#ipp_dstate_e" title="Document states">ipp_dstate_e</a></li>
        <li><a href="#ipp_finish_e" title="Finishings">ipp_finish_e</a></li>
+       <li><a href="#ipp_jcollate_e" title="Job collation types">ipp_jcollate_e</a></li>
        <li><a href="#ipp_jstate_e" title="Job states">ipp_jstate_e</a></li>
        <li><a href="#ipp_op_e" title="IPP operations">ipp_op_e</a></li>
        <li><a href="#ipp_orient_e" title="Orientation values">ipp_orient_e</a></li>
@@ -1066,7 +1097,7 @@ void cupsEncodeOptions2 (<br>
 &nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_t">ipp_t</a> *ipp,<br>
 &nbsp;&nbsp;&nbsp;&nbsp;int num_options,<br>
 &nbsp;&nbsp;&nbsp;&nbsp;cups_option_t *options,<br>
-&nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_tag_t">ipp_tag_t</a> group_tag<br>
+&nbsp;&nbsp;&nbsp;&nbsp;ipp_tag_t group_tag<br>
 );</p>
 <h4 class="parameters">Parameters</h4>
 <dl>
@@ -1186,7 +1217,8 @@ the request respectively.
 <h4 class="discussion">Discussion</h4>
 <p class="discussion">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.
+additional data, use httpRead() after getting a successful response,
+otherwise call httpFlush() to complete the response processing.
 
 </p>
 <h3 class="function"><a name="cupsLastError">cupsLastError</a></h3>
@@ -2026,6 +2058,19 @@ off_t httpGetLength2 (<br>
 content larger than 2^31 - 1.
 
 </p>
+<h3 class="function"><a name="httpGetState">httpGetState</a></h3>
+<p class="description">Get the current state of the HTTP request.</p>
+<p class="code">
+<a href="#http_state_t">http_state_t</a> httpGetState (<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#http_t">http_t</a> *http<br>
+);</p>
+<h4 class="parameters">Parameters</h4>
+<dl>
+<dt>http</dt>
+<dd class="description">Connection to server</dd>
+</dl>
+<h4 class="returnvalue">Return Value</h4>
+<p class="description">HTTP state</p>
 <h3 class="function"><span class="info">&nbsp;CUPS 1.2/Mac OS X 10.5&nbsp;</span><a name="httpGetStatus">httpGetStatus</a></h3>
 <p class="description">Get the status of the last HTTP request.</p>
 <p class="code">
@@ -2086,6 +2131,19 @@ char *httpGetSubField2 (<br>
 </dl>
 <h4 class="returnvalue">Return Value</h4>
 <p class="description">Value or NULL</p>
+<h3 class="function"><a name="httpGetVersion">httpGetVersion</a></h3>
+<p class="description">Get the HTTP version at the other end.</p>
+<p class="code">
+<a href="#http_version_t">http_version_t</a> httpGetVersion (<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#http_t">http_t</a> *http<br>
+);</p>
+<h4 class="parameters">Parameters</h4>
+<dl>
+<dt>http</dt>
+<dd class="description">Connection to server</dd>
+</dl>
+<h4 class="returnvalue">Return Value</h4>
+<p class="description">Version number</p>
 <h3 class="function"><a name="httpGets">httpGets</a></h3>
 <p class="description">Get a line of text from a HTTP connection.</p>
 <p class="code">
@@ -2650,7 +2708,7 @@ ssize_t httpWrite2 (<br>
 <p class="code">
 <a href="#ipp_attribute_t">ipp_attribute_t</a> *ippAddBoolean (<br>
 &nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_t">ipp_t</a> *ipp,<br>
-&nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_tag_t">ipp_tag_t</a> group,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;ipp_tag_t group,<br>
 &nbsp;&nbsp;&nbsp;&nbsp;const char *name,<br>
 &nbsp;&nbsp;&nbsp;&nbsp;char value<br>
 );</p>
@@ -2667,12 +2725,21 @@ ssize_t httpWrite2 (<br>
 </dl>
 <h4 class="returnvalue">Return Value</h4>
 <p class="description">New attribute</p>
+<h4 class="discussion">Discussion</h4>
+<p class="discussion">The <code>ipp</code> parameter refers to an IPP message previously created using the
+<a href="#ippNew"><code>ippNew</code></a> or <a href="#ippNewRequest"><code>ippNewRequest</code></a> functions.<br>
+<br>
+The <code>group</code> parameter specifies the IPP attribute group tag: none
+(<code>IPP_TAG_ZERO</code>, for member attributes), document (<code>IPP_TAG_DOCUMENT</code>),
+event notification (<code>IPP_TAG_EVENT_NOTIFICATION</code>), operation
+(<code>IPP_TAG_OPERATION</code>), printer (<code>IPP_TAG_PRINTER</code>), subscription
+(<code>IPP_TAG_SUBSCRIPTION</code>), or unsupported (<code>IPP_TAG_UNSUPPORTED_GROUP</code>).</p>
 <h3 class="function"><a name="ippAddBooleans">ippAddBooleans</a></h3>
 <p class="description">Add an array of boolean values.</p>
 <p class="code">
 <a href="#ipp_attribute_t">ipp_attribute_t</a> *ippAddBooleans (<br>
 &nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_t">ipp_t</a> *ipp,<br>
-&nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_tag_t">ipp_tag_t</a> group,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;ipp_tag_t group,<br>
 &nbsp;&nbsp;&nbsp;&nbsp;const char *name,<br>
 &nbsp;&nbsp;&nbsp;&nbsp;int num_values,<br>
 &nbsp;&nbsp;&nbsp;&nbsp;const char *values<br>
@@ -2692,12 +2759,21 @@ ssize_t httpWrite2 (<br>
 </dl>
 <h4 class="returnvalue">Return Value</h4>
 <p class="description">New attribute</p>
+<h4 class="discussion">Discussion</h4>
+<p class="discussion">The <code>ipp</code> parameter refers to an IPP message previously created using the
+<a href="#ippNew"><code>ippNew</code></a> or <a href="#ippNewRequest"><code>ippNewRequest</code></a> functions.<br>
+<br>
+The <code>group</code> parameter specifies the IPP attribute group tag: none
+(<code>IPP_TAG_ZERO</code>, for member attributes), document (<code>IPP_TAG_DOCUMENT</code>),
+event notification (<code>IPP_TAG_EVENT_NOTIFICATION</code>), operation
+(<code>IPP_TAG_OPERATION</code>), printer (<code>IPP_TAG_PRINTER</code>), subscription
+(<code>IPP_TAG_SUBSCRIPTION</code>), or unsupported (<code>IPP_TAG_UNSUPPORTED_GROUP</code>).</p>
 <h3 class="function"><span class="info">&nbsp;CUPS 1.1.19/Mac OS X 10.3&nbsp;</span><a name="ippAddCollection">ippAddCollection</a></h3>
 <p class="description">Add a collection value.</p>
 <p class="code">
 <a href="#ipp_attribute_t">ipp_attribute_t</a> *ippAddCollection (<br>
 &nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_t">ipp_t</a> *ipp,<br>
-&nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_tag_t">ipp_tag_t</a> group,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;ipp_tag_t group,<br>
 &nbsp;&nbsp;&nbsp;&nbsp;const char *name,<br>
 &nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_t">ipp_t</a> *value<br>
 );</p>
@@ -2714,12 +2790,23 @@ ssize_t httpWrite2 (<br>
 </dl>
 <h4 class="returnvalue">Return Value</h4>
 <p class="description">New attribute</p>
+<h4 class="discussion">Discussion</h4>
+<p class="discussion">The <code>ipp</code> parameter refers to an IPP message previously created using the
+<a href="#ippNew"><code>ippNew</code></a> or <a href="#ippNewRequest"><code>ippNewRequest</code></a> functions.<br>
+<br>
+The <code>group</code> parameter specifies the IPP attribute group tag: none
+(<code>IPP_TAG_ZERO</code>, for member attributes), document (<code>IPP_TAG_DOCUMENT</code>),
+event notification (<code>IPP_TAG_EVENT_NOTIFICATION</code>), operation
+(<code>IPP_TAG_OPERATION</code>), printer (<code>IPP_TAG_PRINTER</code>), subscription
+(<code>IPP_TAG_SUBSCRIPTION</code>), or unsupported (<code>IPP_TAG_UNSUPPORTED_GROUP</code>).
+
+</p>
 <h3 class="function"><span class="info">&nbsp;CUPS 1.1.19/Mac OS X 10.3&nbsp;</span><a name="ippAddCollections">ippAddCollections</a></h3>
 <p class="description">Add an array of collection values.</p>
 <p class="code">
 <a href="#ipp_attribute_t">ipp_attribute_t</a> *ippAddCollections (<br>
 &nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_t">ipp_t</a> *ipp,<br>
-&nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_tag_t">ipp_tag_t</a> group,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;ipp_tag_t group,<br>
 &nbsp;&nbsp;&nbsp;&nbsp;const char *name,<br>
 &nbsp;&nbsp;&nbsp;&nbsp;int num_values,<br>
 &nbsp;&nbsp;&nbsp;&nbsp;const <a href="#ipp_t">ipp_t</a> **values<br>
@@ -2739,12 +2826,23 @@ ssize_t httpWrite2 (<br>
 </dl>
 <h4 class="returnvalue">Return Value</h4>
 <p class="description">New attribute</p>
+<h4 class="discussion">Discussion</h4>
+<p class="discussion">The <code>ipp</code> parameter refers to an IPP message previously created using the
+<a href="#ippNew"><code>ippNew</code></a> or <a href="#ippNewRequest"><code>ippNewRequest</code></a> functions.<br>
+<br>
+The <code>group</code> parameter specifies the IPP attribute group tag: none
+(<code>IPP_TAG_ZERO</code>, for member attributes), document (<code>IPP_TAG_DOCUMENT</code>),
+event notification (<code>IPP_TAG_EVENT_NOTIFICATION</code>), operation
+(<code>IPP_TAG_OPERATION</code>), printer (<code>IPP_TAG_PRINTER</code>), subscription
+(<code>IPP_TAG_SUBSCRIPTION</code>), or unsupported (<code>IPP_TAG_UNSUPPORTED_GROUP</code>).
+
+</p>
 <h3 class="function"><a name="ippAddDate">ippAddDate</a></h3>
 <p class="description">Add a date attribute to an IPP message.</p>
 <p class="code">
 <a href="#ipp_attribute_t">ipp_attribute_t</a> *ippAddDate (<br>
 &nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_t">ipp_t</a> *ipp,<br>
-&nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_tag_t">ipp_tag_t</a> group,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;ipp_tag_t group,<br>
 &nbsp;&nbsp;&nbsp;&nbsp;const char *name,<br>
 &nbsp;&nbsp;&nbsp;&nbsp;const <a href="#ipp_uchar_t">ipp_uchar_t</a> *value<br>
 );</p>
@@ -2761,13 +2859,22 @@ ssize_t httpWrite2 (<br>
 </dl>
 <h4 class="returnvalue">Return Value</h4>
 <p class="description">New attribute</p>
+<h4 class="discussion">Discussion</h4>
+<p class="discussion">The <code>ipp</code> parameter refers to an IPP message previously created using the
+<a href="#ippNew"><code>ippNew</code></a> or <a href="#ippNewRequest"><code>ippNewRequest</code></a> functions.<br>
+<br>
+The <code>group</code> parameter specifies the IPP attribute group tag: none
+(<code>IPP_TAG_ZERO</code>, for member attributes), document (<code>IPP_TAG_DOCUMENT</code>),
+event notification (<code>IPP_TAG_EVENT_NOTIFICATION</code>), operation
+(<code>IPP_TAG_OPERATION</code>), printer (<code>IPP_TAG_PRINTER</code>), subscription
+(<code>IPP_TAG_SUBSCRIPTION</code>), or unsupported (<code>IPP_TAG_UNSUPPORTED_GROUP</code>).</p>
 <h3 class="function"><a name="ippAddInteger">ippAddInteger</a></h3>
 <p class="description">Add a integer attribute to an IPP message.</p>
 <p class="code">
 <a href="#ipp_attribute_t">ipp_attribute_t</a> *ippAddInteger (<br>
 &nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_t">ipp_t</a> *ipp,<br>
-&nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_tag_t">ipp_tag_t</a> group,<br>
-&nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_tag_t">ipp_tag_t</a> type,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;ipp_tag_t group,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;ipp_tag_t value_tag,<br>
 &nbsp;&nbsp;&nbsp;&nbsp;const char *name,<br>
 &nbsp;&nbsp;&nbsp;&nbsp;int value<br>
 );</p>
@@ -2777,7 +2884,7 @@ ssize_t httpWrite2 (<br>
 <dd class="description">IPP message</dd>
 <dt>group</dt>
 <dd class="description">IPP group</dd>
-<dt>type</dt>
+<dt>value_tag</dt>
 <dd class="description">Type of attribute</dd>
 <dt>name</dt>
 <dd class="description">Name of attribute</dd>
@@ -2786,13 +2893,25 @@ ssize_t httpWrite2 (<br>
 </dl>
 <h4 class="returnvalue">Return Value</h4>
 <p class="description">New attribute</p>
+<h4 class="discussion">Discussion</h4>
+<p class="discussion">The <code>ipp</code> parameter refers to an IPP message previously created using the
+<a href="#ippNew"><code>ippNew</code></a> or <a href="#ippNewRequest"><code>ippNewRequest</code></a> functions.<br>
+<br>
+The <code>group</code> parameter specifies the IPP attribute group tag: none
+(<code>IPP_TAG_ZERO</code>, for member attributes), document (<code>IPP_TAG_DOCUMENT</code>),
+event notification (<code>IPP_TAG_EVENT_NOTIFICATION</code>), operation
+(<code>IPP_TAG_OPERATION</code>), printer (<code>IPP_TAG_PRINTER</code>), subscription
+(<code>IPP_TAG_SUBSCRIPTION</code>), or unsupported (<code>IPP_TAG_UNSUPPORTED_GROUP</code>).<br>
+<br>
+Supported values include enum (<code>IPP_TAG_ENUM</code>) and integer
+(<code>IPP_TAG_INTEGER</code>).</p>
 <h3 class="function"><a name="ippAddIntegers">ippAddIntegers</a></h3>
 <p class="description">Add an array of integer values.</p>
 <p class="code">
 <a href="#ipp_attribute_t">ipp_attribute_t</a> *ippAddIntegers (<br>
 &nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_t">ipp_t</a> *ipp,<br>
-&nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_tag_t">ipp_tag_t</a> group,<br>
-&nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_tag_t">ipp_tag_t</a> type,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;ipp_tag_t group,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;ipp_tag_t value_tag,<br>
 &nbsp;&nbsp;&nbsp;&nbsp;const char *name,<br>
 &nbsp;&nbsp;&nbsp;&nbsp;int num_values,<br>
 &nbsp;&nbsp;&nbsp;&nbsp;const int *values<br>
@@ -2803,7 +2922,7 @@ ssize_t httpWrite2 (<br>
 <dd class="description">IPP message</dd>
 <dt>group</dt>
 <dd class="description">IPP group</dd>
-<dt>type</dt>
+<dt>value_tag</dt>
 <dd class="description">Type of attribute</dd>
 <dt>name</dt>
 <dd class="description">Name of attribute</dd>
@@ -2814,12 +2933,24 @@ ssize_t httpWrite2 (<br>
 </dl>
 <h4 class="returnvalue">Return Value</h4>
 <p class="description">New attribute</p>
+<h4 class="discussion">Discussion</h4>
+<p class="discussion">The <code>ipp</code> parameter refers to an IPP message previously created using the
+<a href="#ippNew"><code>ippNew</code></a> or <a href="#ippNewRequest"><code>ippNewRequest</code></a> functions.<br>
+<br>
+The <code>group</code> parameter specifies the IPP attribute group tag: none
+(<code>IPP_TAG_ZERO</code>, for member attributes), document (<code>IPP_TAG_DOCUMENT</code>),
+event notification (<code>IPP_TAG_EVENT_NOTIFICATION</code>), operation
+(<code>IPP_TAG_OPERATION</code>), printer (<code>IPP_TAG_PRINTER</code>), subscription
+(<code>IPP_TAG_SUBSCRIPTION</code>), or unsupported (<code>IPP_TAG_UNSUPPORTED_GROUP</code>).<br>
+<br>
+Supported values include enum (<code>IPP_TAG_ENUM</code>) and integer
+(<code>IPP_TAG_INTEGER</code>).</p>
 <h3 class="function"><span class="info">&nbsp;CUPS 1.2/Mac OS X 10.5&nbsp;</span><a name="ippAddOctetString">ippAddOctetString</a></h3>
 <p class="description">Add an octetString value to an IPP message.</p>
 <p class="code">
 <a href="#ipp_attribute_t">ipp_attribute_t</a> *ippAddOctetString (<br>
 &nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_t">ipp_t</a> *ipp,<br>
-&nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_tag_t">ipp_tag_t</a> group,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;ipp_tag_t group,<br>
 &nbsp;&nbsp;&nbsp;&nbsp;const char *name,<br>
 &nbsp;&nbsp;&nbsp;&nbsp;const void *data,<br>
 &nbsp;&nbsp;&nbsp;&nbsp;int datalen<br>
@@ -2839,12 +2970,62 @@ ssize_t httpWrite2 (<br>
 </dl>
 <h4 class="returnvalue">Return Value</h4>
 <p class="description">New attribute</p>
+<h4 class="discussion">Discussion</h4>
+<p class="discussion">The <code>ipp</code> parameter refers to an IPP message previously created using the
+<a href="#ippNew"><code>ippNew</code></a> or <a href="#ippNewRequest"><code>ippNewRequest</code></a> functions.<br>
+<br>
+The <code>group</code> parameter specifies the IPP attribute group tag: none
+(<code>IPP_TAG_ZERO</code>, for member attributes), document (<code>IPP_TAG_DOCUMENT</code>),
+event notification (<code>IPP_TAG_EVENT_NOTIFICATION</code>), operation
+(<code>IPP_TAG_OPERATION</code>), printer (<code>IPP_TAG_PRINTER</code>), subscription
+(<code>IPP_TAG_SUBSCRIPTION</code>), or unsupported (<code>IPP_TAG_UNSUPPORTED_GROUP</code>).
+
+</p>
+<h3 class="function"><span class="info">&nbsp;CUPS 1.6&nbsp;</span><a name="ippAddOutOfBand">ippAddOutOfBand</a></h3>
+<p class="description">Add an out-of-band value to an IPP message.</p>
+<p class="code">
+<a href="#ipp_attribute_t">ipp_attribute_t</a> *ippAddOutOfBand (<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_t">ipp_t</a> *ipp,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;ipp_tag_t group,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;ipp_tag_t value_tag,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;const char *name<br>
+);</p>
+<h4 class="parameters">Parameters</h4>
+<dl>
+<dt>ipp</dt>
+<dd class="description">IPP message</dd>
+<dt>group</dt>
+<dd class="description">IPP group</dd>
+<dt>value_tag</dt>
+<dd class="description">Type of attribute</dd>
+<dt>name</dt>
+<dd class="description">Name of attribute</dd>
+</dl>
+<h4 class="returnvalue">Return Value</h4>
+<p class="description">New attribute</p>
+<h4 class="discussion">Discussion</h4>
+<p class="discussion">The <code>ipp</code> parameter refers to an IPP message previously created using the
+<a href="#ippNew"><code>ippNew</code></a> or <a href="#ippNewRequest"><code>ippNewRequest</code></a> functions.<br>
+<br>
+The <code>group</code> parameter specifies the IPP attribute group tag: none
+(<code>IPP_TAG_ZERO</code>, for member attributes), document (<code>IPP_TAG_DOCUMENT</code>),
+event notification (<code>IPP_TAG_EVENT_NOTIFICATION</code>), operation
+(<code>IPP_TAG_OPERATION</code>), printer (<code>IPP_TAG_PRINTER</code>), subscription
+(<code>IPP_TAG_SUBSCRIPTION</code>), or unsupported (<code>IPP_TAG_UNSUPPORTED_GROUP</code>).<br>
+<br>
+Supported out-of-band values include unsupported-value
+(<code>IPP_TAG_UNSUPPORTED_VALUE</code>), default (<code>IPP_TAG_DEFAULT</code>), unknown
+(<code>IPP_TAG_UNKNOWN</code>), no-value (<code>IPP_TAG_NOVALUE</code>), not-settable
+(<code>IPP_TAG_NOTSETTABLE</code>), delete-attribute (<code>IPP_TAG_DELETEATTR</code>), and
+admin-define (<code>IPP_TAG_ADMINDEFINE</code>).
+
+</p>
 <h3 class="function"><a name="ippAddRange">ippAddRange</a></h3>
 <p class="description">Add a range of values to an IPP message.</p>
 <p class="code">
 <a href="#ipp_attribute_t">ipp_attribute_t</a> *ippAddRange (<br>
 &nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_t">ipp_t</a> *ipp,<br>
-&nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_tag_t">ipp_tag_t</a> group,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;ipp_tag_t group,<br>
 &nbsp;&nbsp;&nbsp;&nbsp;const char *name,<br>
 &nbsp;&nbsp;&nbsp;&nbsp;int lower,<br>
 &nbsp;&nbsp;&nbsp;&nbsp;int upper<br>
@@ -2864,12 +3045,23 @@ ssize_t httpWrite2 (<br>
 </dl>
 <h4 class="returnvalue">Return Value</h4>
 <p class="description">New attribute</p>
+<h4 class="discussion">Discussion</h4>
+<p class="discussion">The <code>ipp</code> parameter refers to an IPP message previously created using the
+<a href="#ippNew"><code>ippNew</code></a> or <a href="#ippNewRequest"><code>ippNewRequest</code></a> functions.<br>
+<br>
+The <code>group</code> parameter specifies the IPP attribute group tag: none
+(<code>IPP_TAG_ZERO</code>, for member attributes), document (<code>IPP_TAG_DOCUMENT</code>),
+event notification (<code>IPP_TAG_EVENT_NOTIFICATION</code>), operation
+(<code>IPP_TAG_OPERATION</code>), printer (<code>IPP_TAG_PRINTER</code>), subscription
+(<code>IPP_TAG_SUBSCRIPTION</code>), or unsupported (<code>IPP_TAG_UNSUPPORTED_GROUP</code>).<br>
+<br>
+The <code>lower</code> parameter must be less than or equal to the <code>upper</code> parameter.</p>
 <h3 class="function"><a name="ippAddRanges">ippAddRanges</a></h3>
 <p class="description">Add ranges of values to an IPP message.</p>
 <p class="code">
 <a href="#ipp_attribute_t">ipp_attribute_t</a> *ippAddRanges (<br>
 &nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_t">ipp_t</a> *ipp,<br>
-&nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_tag_t">ipp_tag_t</a> group,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;ipp_tag_t group,<br>
 &nbsp;&nbsp;&nbsp;&nbsp;const char *name,<br>
 &nbsp;&nbsp;&nbsp;&nbsp;int num_values,<br>
 &nbsp;&nbsp;&nbsp;&nbsp;const int *lower,<br>
@@ -2892,12 +3084,21 @@ ssize_t httpWrite2 (<br>
 </dl>
 <h4 class="returnvalue">Return Value</h4>
 <p class="description">New attribute</p>
+<h4 class="discussion">Discussion</h4>
+<p class="discussion">The <code>ipp</code> parameter refers to an IPP message previously created using the
+<a href="#ippNew"><code>ippNew</code></a> or <a href="#ippNewRequest"><code>ippNewRequest</code></a> functions.<br>
+<br>
+The <code>group</code> parameter specifies the IPP attribute group tag: none
+(<code>IPP_TAG_ZERO</code>, for member attributes), document (<code>IPP_TAG_DOCUMENT</code>),
+event notification (<code>IPP_TAG_EVENT_NOTIFICATION</code>), operation
+(<code>IPP_TAG_OPERATION</code>), printer (<code>IPP_TAG_PRINTER</code>), subscription
+(<code>IPP_TAG_SUBSCRIPTION</code>), or unsupported (<code>IPP_TAG_UNSUPPORTED_GROUP</code>).</p>
 <h3 class="function"><a name="ippAddResolution">ippAddResolution</a></h3>
 <p class="description">Add a resolution value to an IPP message.</p>
 <p class="code">
 <a href="#ipp_attribute_t">ipp_attribute_t</a> *ippAddResolution (<br>
 &nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_t">ipp_t</a> *ipp,<br>
-&nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_tag_t">ipp_tag_t</a> group,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;ipp_tag_t group,<br>
 &nbsp;&nbsp;&nbsp;&nbsp;const char *name,<br>
 &nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_res_t">ipp_res_t</a> units,<br>
 &nbsp;&nbsp;&nbsp;&nbsp;int xres,<br>
@@ -2920,12 +3121,21 @@ ssize_t httpWrite2 (<br>
 </dl>
 <h4 class="returnvalue">Return Value</h4>
 <p class="description">New attribute</p>
+<h4 class="discussion">Discussion</h4>
+<p class="discussion">The <code>ipp</code> parameter refers to an IPP message previously created using the
+<a href="#ippNew"><code>ippNew</code></a> or <a href="#ippNewRequest"><code>ippNewRequest</code></a> functions.<br>
+<br>
+The <code>group</code> parameter specifies the IPP attribute group tag: none
+(<code>IPP_TAG_ZERO</code>, for member attributes), document (<code>IPP_TAG_DOCUMENT</code>),
+event notification (<code>IPP_TAG_EVENT_NOTIFICATION</code>), operation
+(<code>IPP_TAG_OPERATION</code>), printer (<code>IPP_TAG_PRINTER</code>), subscription
+(<code>IPP_TAG_SUBSCRIPTION</code>), or unsupported (<code>IPP_TAG_UNSUPPORTED_GROUP</code>).</p>
 <h3 class="function"><a name="ippAddResolutions">ippAddResolutions</a></h3>
 <p class="description">Add resolution values to an IPP message.</p>
 <p class="code">
 <a href="#ipp_attribute_t">ipp_attribute_t</a> *ippAddResolutions (<br>
 &nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_t">ipp_t</a> *ipp,<br>
-&nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_tag_t">ipp_tag_t</a> group,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;ipp_tag_t group,<br>
 &nbsp;&nbsp;&nbsp;&nbsp;const char *name,<br>
 &nbsp;&nbsp;&nbsp;&nbsp;int num_values,<br>
 &nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_res_t">ipp_res_t</a> units,<br>
@@ -2951,6 +3161,15 @@ ssize_t httpWrite2 (<br>
 </dl>
 <h4 class="returnvalue">Return Value</h4>
 <p class="description">New attribute</p>
+<h4 class="discussion">Discussion</h4>
+<p class="discussion">The <code>ipp</code> parameter refers to an IPP message previously created using the
+<a href="#ippNew"><code>ippNew</code></a> or <a href="#ippNewRequest"><code>ippNewRequest</code></a> functions.<br>
+<br>
+The <code>group</code> parameter specifies the IPP attribute group tag: none
+(<code>IPP_TAG_ZERO</code>, for member attributes), document (<code>IPP_TAG_DOCUMENT</code>),
+event notification (<code>IPP_TAG_EVENT_NOTIFICATION</code>), operation
+(<code>IPP_TAG_OPERATION</code>), printer (<code>IPP_TAG_PRINTER</code>), subscription
+(<code>IPP_TAG_SUBSCRIPTION</code>), or unsupported (<code>IPP_TAG_UNSUPPORTED_GROUP</code>).</p>
 <h3 class="function"><a name="ippAddSeparator">ippAddSeparator</a></h3>
 <p class="description">Add a group separator to an IPP message.</p>
 <p class="code">
@@ -2964,15 +3183,18 @@ ssize_t httpWrite2 (<br>
 </dl>
 <h4 class="returnvalue">Return Value</h4>
 <p class="description">New attribute</p>
+<h4 class="discussion">Discussion</h4>
+<p class="discussion">The <code>ipp</code> parameter refers to an IPP message previously created using the
+<a href="#ippNew"><code>ippNew</code></a> or <a href="#ippNewRequest"><code>ippNewRequest</code></a> functions.</p>
 <h3 class="function"><a name="ippAddString">ippAddString</a></h3>
 <p class="description">Add a language-encoded string to an IPP message.</p>
 <p class="code">
 <a href="#ipp_attribute_t">ipp_attribute_t</a> *ippAddString (<br>
 &nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_t">ipp_t</a> *ipp,<br>
-&nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_tag_t">ipp_tag_t</a> group,<br>
-&nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_tag_t">ipp_tag_t</a> type,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;ipp_tag_t group,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;ipp_tag_t value_tag,<br>
 &nbsp;&nbsp;&nbsp;&nbsp;const char *name,<br>
-&nbsp;&nbsp;&nbsp;&nbsp;const char *charset,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;const char *language,<br>
 &nbsp;&nbsp;&nbsp;&nbsp;const char *value<br>
 );</p>
 <h4 class="parameters">Parameters</h4>
@@ -2981,27 +3203,46 @@ ssize_t httpWrite2 (<br>
 <dd class="description">IPP message</dd>
 <dt>group</dt>
 <dd class="description">IPP group</dd>
-<dt>type</dt>
+<dt>value_tag</dt>
 <dd class="description">Type of attribute</dd>
 <dt>name</dt>
 <dd class="description">Name of attribute</dd>
-<dt>charset</dt>
-<dd class="description">Character set</dd>
+<dt>language</dt>
+<dd class="description">Language code</dd>
 <dt>value</dt>
 <dd class="description">Value</dd>
 </dl>
 <h4 class="returnvalue">Return Value</h4>
 <p class="description">New attribute</p>
+<h4 class="discussion">Discussion</h4>
+<p class="discussion">The <code>ipp</code> parameter refers to an IPP message previously created using the
+<a href="#ippNew"><code>ippNew</code></a> or <a href="#ippNewRequest"><code>ippNewRequest</code></a> functions.<br>
+<br>
+The <code>group</code> parameter specifies the IPP attribute group tag: none
+(<code>IPP_TAG_ZERO</code>, for member attributes), document (<code>IPP_TAG_DOCUMENT</code>),
+event notification (<code>IPP_TAG_EVENT_NOTIFICATION</code>), operation
+(<code>IPP_TAG_OPERATION</code>), printer (<code>IPP_TAG_PRINTER</code>), subscription
+(<code>IPP_TAG_SUBSCRIPTION</code>), or unsupported (<code>IPP_TAG_UNSUPPORTED_GROUP</code>).<br>
+<br>
+Supported string values include charset (<code>IPP_TAG_CHARSET</code>), keyword
+(<code>IPP_TAG_KEYWORD</code>), language (<code>IPP_TAG_LANGUAGE</code>), mimeMediaType
+(<code>IPP_TAG_MIMETYPE</code>), name (<code>IPP_TAG_NAME</code>), nameWithLanguage
+(<code>IPP_TAG_NAMELANG), text (</code>code IPP_TAG_TEXT@), textWithLanguage
+(<code>IPP_TAG_TEXTLANG</code>), uri (<code>IPP_TAG_URI</code>), and uriScheme
+(<code>IPP_TAG_URISCHEME</code>).<br>
+<br>
+The <code>language</code> parameter must be non-<code>NULL</code> for nameWithLanguage and
+textWithLanguage string values and must be <code>NULL</code> for all other string values.</p>
 <h3 class="function"><a name="ippAddStrings">ippAddStrings</a></h3>
 <p class="description">Add language-encoded strings to an IPP message.</p>
 <p class="code">
 <a href="#ipp_attribute_t">ipp_attribute_t</a> *ippAddStrings (<br>
 &nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_t">ipp_t</a> *ipp,<br>
-&nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_tag_t">ipp_tag_t</a> group,<br>
-&nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_tag_t">ipp_tag_t</a> type,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;ipp_tag_t group,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;ipp_tag_t value_tag,<br>
 &nbsp;&nbsp;&nbsp;&nbsp;const char *name,<br>
 &nbsp;&nbsp;&nbsp;&nbsp;int num_values,<br>
-&nbsp;&nbsp;&nbsp;&nbsp;const char *charset,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;const char *language,<br>
 &nbsp;&nbsp;&nbsp;&nbsp;const char *const *values<br>
 );</p>
 <h4 class="parameters">Parameters</h4>
@@ -3010,19 +3251,126 @@ ssize_t httpWrite2 (<br>
 <dd class="description">IPP message</dd>
 <dt>group</dt>
 <dd class="description">IPP group</dd>
-<dt>type</dt>
+<dt>value_tag</dt>
 <dd class="description">Type of attribute</dd>
 <dt>name</dt>
 <dd class="description">Name of attribute</dd>
 <dt>num_values</dt>
 <dd class="description">Number of values</dd>
-<dt>charset</dt>
-<dd class="description">Character set</dd>
+<dt>language</dt>
+<dd class="description">Language code (<code>NULL</code> for default)</dd>
 <dt>values</dt>
 <dd class="description">Values</dd>
 </dl>
 <h4 class="returnvalue">Return Value</h4>
 <p class="description">New attribute</p>
+<h4 class="discussion">Discussion</h4>
+<p class="discussion">The <code>ipp</code> parameter refers to an IPP message previously created using the
+<a href="#ippNew"><code>ippNew</code></a> or <a href="#ippNewRequest"><code>ippNewRequest</code></a> functions.<br>
+<br>
+The <code>group</code> parameter specifies the IPP attribute group tag: none
+(<code>IPP_TAG_ZERO</code>, for member attributes), document (<code>IPP_TAG_DOCUMENT</code>),
+event notification (<code>IPP_TAG_EVENT_NOTIFICATION</code>), operation
+(<code>IPP_TAG_OPERATION</code>), printer (<code>IPP_TAG_PRINTER</code>), subscription
+(<code>IPP_TAG_SUBSCRIPTION</code>), or unsupported (<code>IPP_TAG_UNSUPPORTED_GROUP</code>).<br>
+<br>
+Supported string values include charset (<code>IPP_TAG_CHARSET</code>), keyword
+(<code>IPP_TAG_KEYWORD</code>), language (<code>IPP_TAG_LANGUAGE</code>), mimeMediaType
+(<code>IPP_TAG_MIMETYPE</code>), name (<code>IPP_TAG_NAME</code>), nameWithLanguage
+(<code>IPP_TAG_NAMELANG), text (</code>code IPP_TAG_TEXT@), textWithLanguage
+(<code>IPP_TAG_TEXTLANG</code>), uri (<code>IPP_TAG_URI</code>), and uriScheme
+(<code>IPP_TAG_URISCHEME</code>).<br>
+<br>
+The <code>language</code> parameter must be non-<code>NULL</code> for nameWithLanguage and
+textWithLanguage string values and must be <code>NULL</code> for all other string values.</p>
+<h3 class="function"><span class="info">&nbsp;CUPS 1.6&nbsp;</span><a name="ippAttributeString">ippAttributeString</a></h3>
+<p class="description">Convert the attribute's value to a string.</p>
+<p class="code">
+size_t ippAttributeString (<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_attribute_t">ipp_attribute_t</a> *attr,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;char *buffer,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;size_t bufsize<br>
+);</p>
+<h4 class="parameters">Parameters</h4>
+<dl>
+<dt>attr</dt>
+<dd class="description">Attribute</dd>
+<dt>buffer</dt>
+<dd class="description">String buffer or NULL</dd>
+<dt>bufsize</dt>
+<dd class="description">Size of string buffer</dd>
+</dl>
+<h4 class="returnvalue">Return Value</h4>
+<p class="description">Number of bytes less nul</p>
+<h4 class="discussion">Discussion</h4>
+<p class="discussion">Returns the number of bytes that would be written, not including the
+trailing nul. The buffer pointer can be NULL to get the required length,
+just like (v)snprintf.
+
+</p>
+<h3 class="function"><span class="info">&nbsp;CUPS 1.6&nbsp;</span><a name="ippCopyAttribute">ippCopyAttribute</a></h3>
+<p class="description">Copy an attribute.</p>
+<p class="code">
+<a href="#ipp_attribute_t">ipp_attribute_t</a> *ippCopyAttribute (<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_t">ipp_t</a> *dst,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_attribute_t">ipp_attribute_t</a> *srcattr,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;int quickcopy<br>
+);</p>
+<h4 class="parameters">Parameters</h4>
+<dl>
+<dt>dst</dt>
+<dd class="description">Destination IPP message</dd>
+<dt>srcattr</dt>
+<dd class="description">Attribute to copy</dd>
+<dt>quickcopy</dt>
+<dd class="description">1 for a referenced copy, 0 for normal</dd>
+</dl>
+<h4 class="returnvalue">Return Value</h4>
+<p class="description">New attribute</p>
+<h4 class="discussion">Discussion</h4>
+<p class="discussion">The specified attribute, <code>attr</code>, is copied to the destination IPP message.
+When <code>quickcopy</code> is non-zero, a &quot;shallow&quot; reference copy of the attribute is
+created - this should only be done as long as the original source IPP message will
+not be freed for the life of the destination.
+
+</p>
+<h3 class="function"><span class="info">&nbsp;CUPS 1.6&nbsp;</span><a name="ippCopyAttributes">ippCopyAttributes</a></h3>
+<p class="description">Copy attributes from one IPP message to another.</p>
+<p class="code">
+int ippCopyAttributes (<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_t">ipp_t</a> *dst,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_t">ipp_t</a> *src,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;int quickcopy,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_copycb_t">ipp_copycb_t</a> cb,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;void *context<br>
+);</p>
+<h4 class="parameters">Parameters</h4>
+<dl>
+<dt>dst</dt>
+<dd class="description">Destination IPP message</dd>
+<dt>src</dt>
+<dd class="description">Source IPP message</dd>
+<dt>quickcopy</dt>
+<dd class="description">1 for a referenced copy, 0 for normal</dd>
+<dt>cb</dt>
+<dd class="description">Copy callback or <code>NULL</code> for none</dd>
+<dt>context</dt>
+<dd class="description">Context pointer</dd>
+</dl>
+<h4 class="returnvalue">Return Value</h4>
+<p class="description">1 on success, 0 on error</p>
+<h4 class="discussion">Discussion</h4>
+<p class="discussion">Zero or more attributes are copied from the source IPP message, @code@ src, to the
+destination IPP message, <code>dst</code>. When <code>quickcopy</code> is non-zero, a &quot;shallow&quot;
+reference copy of the attribute is created - this should only be done as long as the
+original source IPP message will not be freed for the life of the destination.<br>
+<br>
+The <code>cb</code> and <code>context</code> parameters provide a generic way to &quot;filter&quot; the
+attributes that are copied - the function must return 1 to copy the attribute or
+0 to skip it. The function may also choose to do a partial copy of the source attribute
+itself.
+
+</p>
 <h3 class="function"><a name="ippDateToTime">ippDateToTime</a></h3>
 <p class="description">Convert from RFC 1903 Date/Time format to UNIX time
 in seconds.</p>
@@ -3062,6 +3410,67 @@ void ippDeleteAttribute (<br>
 <dt>attr</dt>
 <dd class="description">Attribute to delete</dd>
 </dl>
+<h3 class="function"><span class="info">&nbsp;CUPS 1.6&nbsp;</span><a name="ippDeleteValues">ippDeleteValues</a></h3>
+<p class="description">Delete values in an attribute.</p>
+<p class="code">
+int ippDeleteValues (<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_t">ipp_t</a> *ipp,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_attribute_t">ipp_attribute_t</a> *attr,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;int element,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;int count<br>
+);</p>
+<h4 class="parameters">Parameters</h4>
+<dl>
+<dt>ipp</dt>
+<dd class="description">IPP message</dd>
+<dt>attr</dt>
+<dd class="description">Attribute</dd>
+<dt>element</dt>
+<dd class="description">Index of first value to delete (0-based)</dd>
+<dt>count</dt>
+<dd class="description">Number of values to delete</dd>
+</dl>
+<h4 class="returnvalue">Return Value</h4>
+<p class="description">1 on success, 0 on failure</p>
+<h4 class="discussion">Discussion</h4>
+<p class="discussion">The <code>element</code> parameter specifies the first value to delete, starting at 0. It
+must be less than the number of values returned by <a href="#ippGetCount"><code>ippGetCount</code></a>.<br>
+<br>
+Deleting all values in an attribute deletes the attribute.
+
+</p>
+<h3 class="function"><a name="ippEnumString">ippEnumString</a></h3>
+<p class="description">Return a string corresponding to the enum value.</p>
+<p class="code">
+const char *ippEnumString (<br>
+&nbsp;&nbsp;&nbsp;&nbsp;const char *attrname,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;int enumvalue<br>
+);</p>
+<h4 class="parameters">Parameters</h4>
+<dl>
+<dt>attrname</dt>
+<dd class="description">Attribute name</dd>
+<dt>enumvalue</dt>
+<dd class="description">Enum value</dd>
+</dl>
+<h4 class="returnvalue">Return Value</h4>
+<p class="description">Enum string</p>
+<h3 class="function"><a name="ippEnumValue">ippEnumValue</a></h3>
+<p class="description">Return the value associated with a given enum string.</p>
+<p class="code">
+int ippEnumValue (<br>
+&nbsp;&nbsp;&nbsp;&nbsp;const char *attrname,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;const char *enumstring<br>
+);</p>
+<h4 class="parameters">Parameters</h4>
+<dl>
+<dt>attrname</dt>
+<dd class="description">Attribute name</dd>
+<dt>enumstring</dt>
+<dd class="description">Enum string</dd>
+</dl>
+<h4 class="returnvalue">Return Value</h4>
+<p class="description">Enum value or -1 if unknown</p>
 <h3 class="function"><a name="ippErrorString">ippErrorString</a></h3>
 <p class="description">Return a name for the given status code.</p>
 <p class="code">
@@ -3094,7 +3503,7 @@ ipp_status_t ippErrorValue (<br>
 <a href="#ipp_attribute_t">ipp_attribute_t</a> *ippFindAttribute (<br>
 &nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_t">ipp_t</a> *ipp,<br>
 &nbsp;&nbsp;&nbsp;&nbsp;const char *name,<br>
-&nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_tag_t">ipp_tag_t</a> type<br>
+&nbsp;&nbsp;&nbsp;&nbsp;ipp_tag_t type<br>
 );</p>
 <h4 class="parameters">Parameters</h4>
 <dl>
@@ -3113,7 +3522,7 @@ ipp_status_t ippErrorValue (<br>
 <a href="#ipp_attribute_t">ipp_attribute_t</a> *ippFindNextAttribute (<br>
 &nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_t">ipp_t</a> *ipp,<br>
 &nbsp;&nbsp;&nbsp;&nbsp;const char *name,<br>
-&nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_tag_t">ipp_tag_t</a> type<br>
+&nbsp;&nbsp;&nbsp;&nbsp;ipp_tag_t type<br>
 );</p>
 <h4 class="parameters">Parameters</h4>
 <dl>
@@ -3126,10 +3535,10 @@ ipp_status_t ippErrorValue (<br>
 </dl>
 <h4 class="returnvalue">Return Value</h4>
 <p class="description">Matching attribute</p>
-<h3 class="function"><a name="ippLength">ippLength</a></h3>
-<p class="description">Compute the length of an IPP message.</p>
+<h3 class="function"><span class="info">&nbsp;CUPS 1.6&nbsp;</span><a name="ippFirstAttribute">ippFirstAttribute</a></h3>
+<p class="description">Return the first attribute in the message.</p>
 <p class="code">
-size_t ippLength (<br>
+<a href="#ipp_attribute_t">ipp_attribute_t</a> *ippFirstAttribute (<br>
 &nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_t">ipp_t</a> *ipp<br>
 );</p>
 <h4 class="parameters">Parameters</h4>
@@ -3138,143 +3547,777 @@ size_t ippLength (<br>
 <dd class="description">IPP message</dd>
 </dl>
 <h4 class="returnvalue">Return Value</h4>
-<p class="description">Size of IPP message</p>
-<h3 class="function"><a name="ippNew">ippNew</a></h3>
-<p class="description">Allocate a new IPP message.</p>
-<p class="code">
-<a href="#ipp_t">ipp_t</a> *ippNew (void);</p>
-<h4 class="returnvalue">Return Value</h4>
-<p class="description">New IPP message</p>
-<h3 class="function"><span class="info">&nbsp;CUPS 1.2/Mac OS X 10.5&nbsp;</span><a name="ippNewRequest">ippNewRequest</a></h3>
-<p class="description">Allocate a new IPP request message.</p>
+<p class="description">First attribute or <code>NULL</code> if none</p>
+<h3 class="function"><span class="info">&nbsp;CUPS 1.6&nbsp;</span><a name="ippGetBoolean">ippGetBoolean</a></h3>
+<p class="description">Get a boolean value for an attribute.</p>
 <p class="code">
-<a href="#ipp_t">ipp_t</a> *ippNewRequest (<br>
-&nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_op_t">ipp_op_t</a> op<br>
+int ippGetBoolean (<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_attribute_t">ipp_attribute_t</a> *attr,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;int element<br>
 );</p>
 <h4 class="parameters">Parameters</h4>
 <dl>
-<dt>op</dt>
-<dd class="description">Operation code</dd>
+<dt>attr</dt>
+<dd class="description">IPP attribute</dd>
+<dt>element</dt>
+<dd class="description">Value number (0-based)</dd>
 </dl>
 <h4 class="returnvalue">Return Value</h4>
-<p class="description">IPP request message</p>
+<p class="description">Boolean value or -1 on error</p>
 <h4 class="discussion">Discussion</h4>
-<p class="discussion">The new request message is initialized with the attributes-charset and
-attributes-natural-language attributes added. The
-attributes-natural-language value is derived from the current locale.
+<p class="discussion">The <code>element</code> parameter specifies which value to get from 0 to
+<a href="#ippGetCount(attr)"><code>ippGetCount(attr)</code></a> - 1.
 
 </p>
-<h3 class="function"><span class="info">&nbsp;CUPS 1.2/Mac OS X 10.5&nbsp;</span><a name="ippOpString">ippOpString</a></h3>
-<p class="description">Return a name for the given operation id.</p>
+<h3 class="function"><span class="info">&nbsp;CUPS 1.6&nbsp;</span><a name="ippGetCollection">ippGetCollection</a></h3>
+<p class="description">Get a collection value for an attribute.</p>
 <p class="code">
-const char *ippOpString (<br>
-&nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_op_t">ipp_op_t</a> op<br>
+<a href="#ipp_t">ipp_t</a> *ippGetCollection (<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_attribute_t">ipp_attribute_t</a> *attr,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;int element<br>
 );</p>
 <h4 class="parameters">Parameters</h4>
 <dl>
-<dt>op</dt>
-<dd class="description">Operation ID</dd>
+<dt>attr</dt>
+<dd class="description">IPP attribute</dd>
+<dt>element</dt>
+<dd class="description">Value number (0-based)</dd>
 </dl>
 <h4 class="returnvalue">Return Value</h4>
-<p class="description">Name</p>
-<h3 class="function"><span class="info">&nbsp;CUPS 1.2/Mac OS X 10.5&nbsp;</span><a name="ippOpValue">ippOpValue</a></h3>
-<p class="description">Return an operation id for the given name.</p>
+<p class="description">Collection value or <code>NULL</code> on error</p>
+<h4 class="discussion">Discussion</h4>
+<p class="discussion">The <code>element</code> parameter specifies which value to get from 0 to
+<a href="#ippGetCount(attr)"><code>ippGetCount(attr)</code></a> - 1.
+
+</p>
+<h3 class="function"><span class="info">&nbsp;CUPS 1.6&nbsp;</span><a name="ippGetCount">ippGetCount</a></h3>
+<p class="description">Get the number of values in an attribute.</p>
 <p class="code">
-<a href="#ipp_op_t">ipp_op_t</a> ippOpValue (<br>
-&nbsp;&nbsp;&nbsp;&nbsp;const char *name<br>
+int ippGetCount (<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_attribute_t">ipp_attribute_t</a> *attr<br>
 );</p>
 <h4 class="parameters">Parameters</h4>
 <dl>
-<dt>name</dt>
-<dd class="description">Textual name</dd>
+<dt>attr</dt>
+<dd class="description">IPP attribute</dd>
 </dl>
 <h4 class="returnvalue">Return Value</h4>
-<p class="description">Operation ID</p>
-<h3 class="function"><a name="ippPort">ippPort</a></h3>
-<p class="description">Return the default IPP port number.</p>
+<p class="description">Number of values or -1 on error</p>
+<h3 class="function"><span class="info">&nbsp;CUPS 1.6&nbsp;</span><a name="ippGetGroupTag">ippGetGroupTag</a></h3>
+<p class="description">Get the group associated with an attribute.</p>
 <p class="code">
-int ippPort (void);</p>
+ipp_tag_t ippGetGroupTag (<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_attribute_t">ipp_attribute_t</a> *attr<br>
+);</p>
+<h4 class="parameters">Parameters</h4>
+<dl>
+<dt>attr</dt>
+<dd class="description">IPP attribute</dd>
+</dl>
 <h4 class="returnvalue">Return Value</h4>
-<p class="description">Port number</p>
-<h3 class="function"><a name="ippRead">ippRead</a></h3>
-<p class="description">Read data for an IPP message from a HTTP connection.</p>
+<p class="description">Group tag or <code>IPP_TAG_ZERO</code> on error</p>
+<h3 class="function"><span class="info">&nbsp;CUPS 1.6&nbsp;</span><a name="ippGetInteger">ippGetInteger</a></h3>
+<p class="description">Get the integer/enum value for an attribute.</p>
 <p class="code">
-<a href="#ipp_state_t">ipp_state_t</a> ippRead (<br>
-&nbsp;&nbsp;&nbsp;&nbsp;<a href="#http_t">http_t</a> *http,<br>
-&nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_t">ipp_t</a> *ipp<br>
+int ippGetInteger (<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_attribute_t">ipp_attribute_t</a> *attr,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;int element<br>
 );</p>
 <h4 class="parameters">Parameters</h4>
 <dl>
-<dt>http</dt>
-<dd class="description">HTTP connection</dd>
-<dt>ipp</dt>
-<dd class="description">IPP data</dd>
+<dt>attr</dt>
+<dd class="description">IPP attribute</dd>
+<dt>element</dt>
+<dd class="description">Value number (0-based)</dd>
 </dl>
 <h4 class="returnvalue">Return Value</h4>
-<p class="description">Current state</p>
-<h3 class="function"><span class="info">&nbsp;CUPS 1.1.19/Mac OS X 10.3&nbsp;</span><a name="ippReadFile">ippReadFile</a></h3>
-<p class="description">Read data for an IPP message from a file.</p>
+<p class="description">Value or -1 on error</p>
+<h4 class="discussion">Discussion</h4>
+<p class="discussion">The <code>element</code> parameter specifies which value to get from 0 to
+<a href="#ippGetCount(attr)"><code>ippGetCount(attr)</code></a> - 1.
+
+</p>
+<h3 class="function"><span class="info">&nbsp;CUPS 1.6&nbsp;</span><a name="ippGetName">ippGetName</a></h3>
+<p class="description">Get the attribute name.</p>
 <p class="code">
-<a href="#ipp_state_t">ipp_state_t</a> ippReadFile (<br>
-&nbsp;&nbsp;&nbsp;&nbsp;int fd,<br>
-&nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_t">ipp_t</a> *ipp<br>
+const char *ippGetName (<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_attribute_t">ipp_attribute_t</a> *attr<br>
 );</p>
 <h4 class="parameters">Parameters</h4>
 <dl>
-<dt>fd</dt>
-<dd class="description">HTTP data</dd>
-<dt>ipp</dt>
-<dd class="description">IPP data</dd>
+<dt>attr</dt>
+<dd class="description">IPP attribute</dd>
 </dl>
 <h4 class="returnvalue">Return Value</h4>
-<p class="description">Current state</p>
-<h3 class="function"><span class="info">&nbsp;CUPS 1.2/Mac OS X 10.5&nbsp;</span><a name="ippReadIO">ippReadIO</a></h3>
-<p class="description">Read data for an IPP message.</p>
+<p class="description">Attribute name or <code>NULL</code> for separators</p>
+<h3 class="function"><span class="info">&nbsp;CUPS 1.6&nbsp;</span><a name="ippGetOperation">ippGetOperation</a></h3>
+<p class="description">Get the operation ID in an IPP message.</p>
 <p class="code">
-<a href="#ipp_state_t">ipp_state_t</a> ippReadIO (<br>
-&nbsp;&nbsp;&nbsp;&nbsp;void *src,<br>
-&nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_iocb_t">ipp_iocb_t</a> cb,<br>
-&nbsp;&nbsp;&nbsp;&nbsp;int blocking,<br>
-&nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_t">ipp_t</a> *parent,<br>
+ipp_op_t ippGetOperation (<br>
 &nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_t">ipp_t</a> *ipp<br>
 );</p>
 <h4 class="parameters">Parameters</h4>
 <dl>
-<dt>src</dt>
-<dd class="description">Data source</dd>
-<dt>cb</dt>
-<dd class="description">Read callback function</dd>
-<dt>blocking</dt>
-<dd class="description">Use blocking IO?</dd>
-<dt>parent</dt>
-<dd class="description">Parent request, if any</dd>
 <dt>ipp</dt>
-<dd class="description">IPP data</dd>
+<dd class="description">IPP request message</dd>
 </dl>
 <h4 class="returnvalue">Return Value</h4>
-<p class="description">Current state</p>
-<h3 class="function"><a name="ippSetPort">ippSetPort</a></h3>
-<p class="description">Set the default port number.</p>
+<p class="description">Operation ID or -1 on error</p>
+<h3 class="function"><span class="info">&nbsp;CUPS 1.6&nbsp;</span><a name="ippGetRequestId">ippGetRequestId</a></h3>
+<p class="description">Get the request ID from an IPP message.</p>
 <p class="code">
-void ippSetPort (<br>
-&nbsp;&nbsp;&nbsp;&nbsp;int p<br>
+int ippGetRequestId (<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_t">ipp_t</a> *ipp<br>
 );</p>
 <h4 class="parameters">Parameters</h4>
 <dl>
-<dt>p</dt>
-<dd class="description">Port number to use</dd>
+<dt>ipp</dt>
+<dd class="description">IPP message</dd>
 </dl>
-<h3 class="function"><span class="info">&nbsp;CUPS 1.4/Mac OS X 10.6&nbsp;</span><a name="ippTagString">ippTagString</a></h3>
-<p class="description">Return the tag name corresponding to a tag value.</p>
-<p class="code">
-const char *ippTagString (<br>
-&nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_tag_t">ipp_tag_t</a> tag<br>
+<h4 class="returnvalue">Return Value</h4>
+<p class="description">Request ID or -1 on error</p>
+<h3 class="function"><span class="info">&nbsp;CUPS 1.6&nbsp;</span><a name="ippGetResolution">ippGetResolution</a></h3>
+<p class="description">Get a resolution value for an attribute.</p>
+<p class="code">
+int ippGetResolution (<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_attribute_t">ipp_attribute_t</a> *attr,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;int element,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;int *yres,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_res_t">ipp_res_t</a> *units<br>
 );</p>
 <h4 class="parameters">Parameters</h4>
 <dl>
-<dt>tag</dt>
-<dd class="description">Tag value</dd>
-</dl>
+<dt>attr</dt>
+<dd class="description">IPP attribute</dd>
+<dt>element</dt>
+<dd class="description">Value number (0-based)</dd>
+<dt>yres</dt>
+<dd class="description">Vertical/feed resolution</dd>
+<dt>units</dt>
+<dd class="description">Units for resolution</dd>
+</dl>
+<h4 class="returnvalue">Return Value</h4>
+<p class="description">Horizontal/cross feed resolution or -1</p>
+<h4 class="discussion">Discussion</h4>
+<p class="discussion">The <code>element</code> parameter specifies which value to get from 0 to
+<a href="#ippGetCount(attr)"><code>ippGetCount(attr)</code></a> - 1.
+
+</p>
+<h3 class="function"><span class="info">&nbsp;CUPS 1.6&nbsp;</span><a name="ippGetStatusCode">ippGetStatusCode</a></h3>
+<p class="description">Get the status code from an IPP response or event message.</p>
+<p class="code">
+ipp_status_t ippGetStatusCode (<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_t">ipp_t</a> *ipp<br>
+);</p>
+<h4 class="parameters">Parameters</h4>
+<dl>
+<dt>ipp</dt>
+<dd class="description">IPP response or event message</dd>
+</dl>
+<h4 class="returnvalue">Return Value</h4>
+<p class="description">Status code in IPP message</p>
+<h3 class="function"><a name="ippGetString">ippGetString</a></h3>
+<p class="description">Return the value...</p>
+<p class="code">
+const char *ippGetString (<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_attribute_t">ipp_attribute_t</a> *attr,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;int element,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;const char **language<br>
+);</p>
+<h4 class="parameters">Parameters</h4>
+<dl>
+<dt>attr</dt>
+<dd class="description">IPP attribute</dd>
+<dt>element</dt>
+<dd class="description">Value number (0-based)</dd>
+<dt>language</dt>
+<dd class="description">Language code (<code>NULL</code> for don't care)</dd>
+</dl>
+<h4 class="returnvalue">Return Value</h4>
+<p class="description">Get the string and optionally the language code for an attribute.</p>
+<p class="discussion">The <code>element</code> parameter specifies which value to get from 0 to
+<a href="#ippGetCount(attr)"><code>ippGetCount(attr)</code></a> - 1.
+
+</p>
+<h3 class="function"><span class="info">&nbsp;CUPS 1.6&nbsp;</span><a name="ippGetValueTag">ippGetValueTag</a></h3>
+<p class="description">Get the value tag for an attribute.</p>
+<p class="code">
+ipp_tag_t ippGetValueTag (<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_attribute_t">ipp_attribute_t</a> *attr<br>
+);</p>
+<h4 class="parameters">Parameters</h4>
+<dl>
+<dt>attr</dt>
+<dd class="description">IPP attribute</dd>
+</dl>
+<h4 class="returnvalue">Return Value</h4>
+<p class="description">Value tag or <code>IPP_TAG_ZERO</code> on error</p>
+<h3 class="function"><span class="info">&nbsp;CUPS 1.6&nbsp;</span><a name="ippGetVersion">ippGetVersion</a></h3>
+<p class="description">Get the major and minor version number from an IPP message.</p>
+<p class="code">
+int ippGetVersion (<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_t">ipp_t</a> *ipp,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;int *minor<br>
+);</p>
+<h4 class="parameters">Parameters</h4>
+<dl>
+<dt>ipp</dt>
+<dd class="description">IPP message</dd>
+<dt>minor</dt>
+<dd class="description">Minor version number or <code>NULL</code></dd>
+</dl>
+<h4 class="returnvalue">Return Value</h4>
+<p class="description">Major version number or -1 on error</p>
+<h3 class="function"><a name="ippLength">ippLength</a></h3>
+<p class="description">Compute the length of an IPP message.</p>
+<p class="code">
+size_t ippLength (<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_t">ipp_t</a> *ipp<br>
+);</p>
+<h4 class="parameters">Parameters</h4>
+<dl>
+<dt>ipp</dt>
+<dd class="description">IPP message</dd>
+</dl>
+<h4 class="returnvalue">Return Value</h4>
+<p class="description">Size of IPP message</p>
+<h3 class="function"><a name="ippNew">ippNew</a></h3>
+<p class="description">Allocate a new IPP message.</p>
+<p class="code">
+<a href="#ipp_t">ipp_t</a> *ippNew (void);</p>
+<h4 class="returnvalue">Return Value</h4>
+<p class="description">New IPP message</p>
+<h3 class="function"><span class="info">&nbsp;CUPS 1.2/Mac OS X 10.5&nbsp;</span><a name="ippNewRequest">ippNewRequest</a></h3>
+<p class="description">Allocate a new IPP request message.</p>
+<p class="code">
+<a href="#ipp_t">ipp_t</a> *ippNewRequest (<br>
+&nbsp;&nbsp;&nbsp;&nbsp;ipp_op_t op<br>
+);</p>
+<h4 class="parameters">Parameters</h4>
+<dl>
+<dt>op</dt>
+<dd class="description">Operation code</dd>
+</dl>
+<h4 class="returnvalue">Return Value</h4>
+<p class="description">IPP request message</p>
+<h4 class="discussion">Discussion</h4>
+<p class="discussion">The new request message is initialized with the attributes-charset and
+attributes-natural-language attributes added. The
+attributes-natural-language value is derived from the current locale.
+
+</p>
+<h3 class="function"><span class="info">&nbsp;CUPS 1.6&nbsp;</span><a name="ippNextAttribute">ippNextAttribute</a></h3>
+<p class="description">Return the next attribute in the message.</p>
+<p class="code">
+<a href="#ipp_attribute_t">ipp_attribute_t</a> *ippNextAttribute (<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_t">ipp_t</a> *ipp<br>
+);</p>
+<h4 class="parameters">Parameters</h4>
+<dl>
+<dt>ipp</dt>
+<dd class="description">IPP message</dd>
+</dl>
+<h4 class="returnvalue">Return Value</h4>
+<p class="description">Next attribute or <code>NULL</code> if none</p>
+<h3 class="function"><span class="info">&nbsp;CUPS 1.2/Mac OS X 10.5&nbsp;</span><a name="ippOpString">ippOpString</a></h3>
+<p class="description">Return a name for the given operation id.</p>
+<p class="code">
+const char *ippOpString (<br>
+&nbsp;&nbsp;&nbsp;&nbsp;ipp_op_t op<br>
+);</p>
+<h4 class="parameters">Parameters</h4>
+<dl>
+<dt>op</dt>
+<dd class="description">Operation ID</dd>
+</dl>
+<h4 class="returnvalue">Return Value</h4>
+<p class="description">Name</p>
+<h3 class="function"><span class="info">&nbsp;CUPS 1.2/Mac OS X 10.5&nbsp;</span><a name="ippOpValue">ippOpValue</a></h3>
+<p class="description">Return an operation id for the given name.</p>
+<p class="code">
+ipp_op_t ippOpValue (<br>
+&nbsp;&nbsp;&nbsp;&nbsp;const char *name<br>
+);</p>
+<h4 class="parameters">Parameters</h4>
+<dl>
+<dt>name</dt>
+<dd class="description">Textual name</dd>
+</dl>
+<h4 class="returnvalue">Return Value</h4>
+<p class="description">Operation ID</p>
+<h3 class="function"><a name="ippPort">ippPort</a></h3>
+<p class="description">Return the default IPP port number.</p>
+<p class="code">
+int ippPort (void);</p>
+<h4 class="returnvalue">Return Value</h4>
+<p class="description">Port number</p>
+<h3 class="function"><a name="ippRead">ippRead</a></h3>
+<p class="description">Read data for an IPP message from a HTTP connection.</p>
+<p class="code">
+<a href="#ipp_state_t">ipp_state_t</a> ippRead (<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#http_t">http_t</a> *http,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_t">ipp_t</a> *ipp<br>
+);</p>
+<h4 class="parameters">Parameters</h4>
+<dl>
+<dt>http</dt>
+<dd class="description">HTTP connection</dd>
+<dt>ipp</dt>
+<dd class="description">IPP data</dd>
+</dl>
+<h4 class="returnvalue">Return Value</h4>
+<p class="description">Current state</p>
+<h3 class="function"><span class="info">&nbsp;CUPS 1.1.19/Mac OS X 10.3&nbsp;</span><a name="ippReadFile">ippReadFile</a></h3>
+<p class="description">Read data for an IPP message from a file.</p>
+<p class="code">
+<a href="#ipp_state_t">ipp_state_t</a> ippReadFile (<br>
+&nbsp;&nbsp;&nbsp;&nbsp;int fd,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_t">ipp_t</a> *ipp<br>
+);</p>
+<h4 class="parameters">Parameters</h4>
+<dl>
+<dt>fd</dt>
+<dd class="description">HTTP data</dd>
+<dt>ipp</dt>
+<dd class="description">IPP data</dd>
+</dl>
+<h4 class="returnvalue">Return Value</h4>
+<p class="description">Current state</p>
+<h3 class="function"><span class="info">&nbsp;CUPS 1.2/Mac OS X 10.5&nbsp;</span><a name="ippReadIO">ippReadIO</a></h3>
+<p class="description">Read data for an IPP message.</p>
+<p class="code">
+<a href="#ipp_state_t">ipp_state_t</a> ippReadIO (<br>
+&nbsp;&nbsp;&nbsp;&nbsp;void *src,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_iocb_t">ipp_iocb_t</a> cb,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;int blocking,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_t">ipp_t</a> *parent,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_t">ipp_t</a> *ipp<br>
+);</p>
+<h4 class="parameters">Parameters</h4>
+<dl>
+<dt>src</dt>
+<dd class="description">Data source</dd>
+<dt>cb</dt>
+<dd class="description">Read callback function</dd>
+<dt>blocking</dt>
+<dd class="description">Use blocking IO?</dd>
+<dt>parent</dt>
+<dd class="description">Parent request, if any</dd>
+<dt>ipp</dt>
+<dd class="description">IPP data</dd>
+</dl>
+<h4 class="returnvalue">Return Value</h4>
+<p class="description">Current state</p>
+<h3 class="function"><span class="info">&nbsp;CUPS 1.6&nbsp;</span><a name="ippSetBoolean">ippSetBoolean</a></h3>
+<p class="description">Set a boolean value in an attribute.</p>
+<p class="code">
+int ippSetBoolean (<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_t">ipp_t</a> *ipp,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_attribute_t">ipp_attribute_t</a> **attr,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;int element,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;int boolvalue<br>
+);</p>
+<h4 class="parameters">Parameters</h4>
+<dl>
+<dt>ipp</dt>
+<dd class="description">IPP message</dd>
+<dt>attr</dt>
+<dd class="description">IPP attribute</dd>
+<dt>element</dt>
+<dd class="description">Value number (0-based)</dd>
+<dt>boolvalue</dt>
+<dd class="description">Boolean value</dd>
+</dl>
+<h4 class="returnvalue">Return Value</h4>
+<p class="description">1 on success, 0 on failure</p>
+<h4 class="discussion">Discussion</h4>
+<p class="discussion">The <code>ipp</code> parameter refers to the IPP message containing the attribute that was
+previously created using the <a href="#ippNew"><code>ippNew</code></a> or <a href="#ippNewRequest"><code>ippNewRequest</code></a> functions.<br>
+<br>
+The <code>attr</code> parameter may be modified as a result of setting the value.<br>
+<br>
+The <code>element</code> parameter specifies which value to set from 0 to
+<a href="#ippGetCount(attr)"><code>ippGetCount(attr)</code></a>.
+
+</p>
+<h3 class="function"><span class="info">&nbsp;CUPS 1.6&nbsp;</span><a name="ippSetCollection">ippSetCollection</a></h3>
+<p class="description">Set a collection value in an attribute.</p>
+<p class="code">
+int ippSetCollection (<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_t">ipp_t</a> *ipp,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_attribute_t">ipp_attribute_t</a> **attr,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;int element,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_t">ipp_t</a> *colvalue<br>
+);</p>
+<h4 class="parameters">Parameters</h4>
+<dl>
+<dt>ipp</dt>
+<dd class="description">IPP message</dd>
+<dt>attr</dt>
+<dd class="description">IPP attribute</dd>
+<dt>element</dt>
+<dd class="description">Value number (0-based)</dd>
+<dt>colvalue</dt>
+<dd class="description">Collection value</dd>
+</dl>
+<h4 class="returnvalue">Return Value</h4>
+<p class="description">1 on success, 0 on failure</p>
+<h4 class="discussion">Discussion</h4>
+<p class="discussion">The <code>ipp</code> parameter refers to the IPP message containing the attribute that was
+previously created using the <a href="#ippNew"><code>ippNew</code></a> or <a href="#ippNewRequest"><code>ippNewRequest</code></a> functions.<br>
+<br>
+The <code>attr</code> parameter may be modified as a result of setting the value.<br>
+<br>
+The <code>element</code> parameter specifies which value to set from 0 to
+<a href="#ippGetCount(attr)"><code>ippGetCount(attr)</code></a>.
+
+</p>
+<h3 class="function"><span class="info">&nbsp;CUPS 1.6&nbsp;</span><a name="ippSetGroupTag">ippSetGroupTag</a></h3>
+<p class="description">Set the group tag of an attribute.</p>
+<p class="code">
+int ippSetGroupTag (<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_t">ipp_t</a> *ipp,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_attribute_t">ipp_attribute_t</a> **attr,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;ipp_tag_t group_tag<br>
+);</p>
+<h4 class="parameters">Parameters</h4>
+<dl>
+<dt>ipp</dt>
+<dd class="description">IPP message</dd>
+<dt>attr</dt>
+<dd class="description">Attribute</dd>
+<dt>group_tag</dt>
+<dd class="description">Group tag</dd>
+</dl>
+<h4 class="returnvalue">Return Value</h4>
+<p class="description">1 on success, 0 on failure</p>
+<h4 class="discussion">Discussion</h4>
+<p class="discussion">The <code>ipp</code> parameter refers to the IPP message containing the attribute that was
+previously created using the <a href="#ippNew"><code>ippNew</code></a> or <a href="#ippNewRequest"><code>ippNewRequest</code></a> functions.<br>
+<br>
+The <code>attr</code> parameter may be modified as a result of setting the value.<br>
+<br>
+The <code>group</code> parameter specifies the IPP attribute group tag: none
+(<code>IPP_TAG_ZERO</code>, for member attributes), document (<code>IPP_TAG_DOCUMENT</code>),
+event notification (<code>IPP_TAG_EVENT_NOTIFICATION</code>), operation
+(<code>IPP_TAG_OPERATION</code>), printer (<code>IPP_TAG_PRINTER</code>), subscription
+(<code>IPP_TAG_SUBSCRIPTION</code>), or unsupported (<code>IPP_TAG_UNSUPPORTED_GROUP</code>).
+
+</p>
+<h3 class="function"><span class="info">&nbsp;CUPS 1.6&nbsp;</span><a name="ippSetInteger">ippSetInteger</a></h3>
+<p class="description">Set an integer or enum value in an attribute.</p>
+<p class="code">
+int ippSetInteger (<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_t">ipp_t</a> *ipp,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_attribute_t">ipp_attribute_t</a> **attr,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;int element,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;int intvalue<br>
+);</p>
+<h4 class="parameters">Parameters</h4>
+<dl>
+<dt>ipp</dt>
+<dd class="description">IPP message</dd>
+<dt>attr</dt>
+<dd class="description">IPP attribute</dd>
+<dt>element</dt>
+<dd class="description">Value number (0-based)</dd>
+<dt>intvalue</dt>
+<dd class="description">Integer/enum value</dd>
+</dl>
+<h4 class="returnvalue">Return Value</h4>
+<p class="description">1 on success, 0 on failure</p>
+<h4 class="discussion">Discussion</h4>
+<p class="discussion">The <code>ipp</code> parameter refers to the IPP message containing the attribute that was
+previously created using the <a href="#ippNew"><code>ippNew</code></a> or <a href="#ippNewRequest"><code>ippNewRequest</code></a> functions.<br>
+<br>
+The <code>attr</code> parameter may be modified as a result of setting the value.<br>
+<br>
+The <code>element</code> parameter specifies which value to set from 0 to
+<a href="#ippGetCount(attr)"><code>ippGetCount(attr)</code></a>.
+
+</p>
+<h3 class="function"><span class="info">&nbsp;CUPS 1.6&nbsp;</span><a name="ippSetName">ippSetName</a></h3>
+<p class="description">Set the name of an attribute.</p>
+<p class="code">
+int ippSetName (<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_t">ipp_t</a> *ipp,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_attribute_t">ipp_attribute_t</a> **attr,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;const char *name<br>
+);</p>
+<h4 class="parameters">Parameters</h4>
+<dl>
+<dt>ipp</dt>
+<dd class="description">IPP message</dd>
+<dt>attr</dt>
+<dd class="description">IPP attribute</dd>
+<dt>name</dt>
+<dd class="description">Attribute name</dd>
+</dl>
+<h4 class="returnvalue">Return Value</h4>
+<p class="description">1 on success, 0 on failure</p>
+<h4 class="discussion">Discussion</h4>
+<p class="discussion">The <code>ipp</code> parameter refers to the IPP message containing the attribute that was
+previously created using the <a href="#ippNew"><code>ippNew</code></a> or <a href="#ippNewRequest"><code>ippNewRequest</code></a> functions.<br>
+<br>
+The <code>attr</code> parameter may be modified as a result of setting the value.
+
+</p>
+<h3 class="function"><span class="info">&nbsp;CUPS 1.6&nbsp;</span><a name="ippSetOperation">ippSetOperation</a></h3>
+<p class="description">Set the operation ID in an IPP request message.</p>
+<p class="code">
+int ippSetOperation (<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_t">ipp_t</a> *ipp,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;ipp_op_t op<br>
+);</p>
+<h4 class="parameters">Parameters</h4>
+<dl>
+<dt>ipp</dt>
+<dd class="description">IPP request message</dd>
+<dt>op</dt>
+<dd class="description">Operation ID</dd>
+</dl>
+<h4 class="returnvalue">Return Value</h4>
+<p class="description">1 on success, 0 on failure</p>
+<h4 class="discussion">Discussion</h4>
+<p class="discussion">The <code>ipp</code> parameter refers to an IPP message previously created using the
+<a href="#ippNew"><code>ippNew</code></a> or <a href="#ippNewRequest"><code>ippNewRequest</code></a> functions.
+
+</p>
+<h3 class="function"><a name="ippSetPort">ippSetPort</a></h3>
+<p class="description">Set the default port number.</p>
+<p class="code">
+void ippSetPort (<br>
+&nbsp;&nbsp;&nbsp;&nbsp;int p<br>
+);</p>
+<h4 class="parameters">Parameters</h4>
+<dl>
+<dt>p</dt>
+<dd class="description">Port number to use</dd>
+</dl>
+<h3 class="function"><span class="info">&nbsp;CUPS 1.6&nbsp;</span><a name="ippSetRange">ippSetRange</a></h3>
+<p class="description">Set a rangeOfInteger value in an attribute.</p>
+<p class="code">
+int ippSetRange (<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_t">ipp_t</a> *ipp,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_attribute_t">ipp_attribute_t</a> **attr,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;int element,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;int lowervalue,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;int uppervalue<br>
+);</p>
+<h4 class="parameters">Parameters</h4>
+<dl>
+<dt>ipp</dt>
+<dd class="description">IPP message</dd>
+<dt>attr</dt>
+<dd class="description">IPP attribute</dd>
+<dt>element</dt>
+<dd class="description">Value number (0-based)</dd>
+<dt>lowervalue</dt>
+<dd class="description">Lower bound for range</dd>
+<dt>uppervalue</dt>
+<dd class="description">Upper bound for range</dd>
+</dl>
+<h4 class="returnvalue">Return Value</h4>
+<p class="description">1 on success, 0 on failure</p>
+<h4 class="discussion">Discussion</h4>
+<p class="discussion">The <code>ipp</code> parameter refers to the IPP message containing the attribute that was
+previously created using the <a href="#ippNew"><code>ippNew</code></a> or <a href="#ippNewRequest"><code>ippNewRequest</code></a> functions.<br>
+<br>
+The <code>attr</code> parameter may be modified as a result of setting the value.<br>
+<br>
+The <code>element</code> parameter specifies which value to set from 0 to
+<a href="#ippGetCount(attr)"><code>ippGetCount(attr)</code></a>.
+
+</p>
+<h3 class="function"><span class="info">&nbsp;CUPS 1.6&nbsp;</span><a name="ippSetRequestId">ippSetRequestId</a></h3>
+<p class="description">Set the request ID in an IPP message.</p>
+<p class="code">
+int ippSetRequestId (<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_t">ipp_t</a> *ipp,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;int request_id<br>
+);</p>
+<h4 class="parameters">Parameters</h4>
+<dl>
+<dt>ipp</dt>
+<dd class="description">IPP message</dd>
+<dt>request_id</dt>
+<dd class="description">Request ID</dd>
+</dl>
+<h4 class="returnvalue">Return Value</h4>
+<p class="description">1 on success, 0 on failure</p>
+<h4 class="discussion">Discussion</h4>
+<p class="discussion">The <code>ipp</code> parameter refers to an IPP message previously created using the
+<a href="#ippNew"><code>ippNew</code></a> or <a href="#ippNewRequest"><code>ippNewRequest</code></a> functions.<br>
+<br>
+The <code>request_id</code> parameter must be greater than 0.
+
+</p>
+<h3 class="function"><span class="info">&nbsp;CUPS 1.6&nbsp;</span><a name="ippSetResolution">ippSetResolution</a></h3>
+<p class="description">Set a resolution value in an attribute.</p>
+<p class="code">
+int ippSetResolution (<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_t">ipp_t</a> *ipp,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_attribute_t">ipp_attribute_t</a> **attr,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;int element,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_res_t">ipp_res_t</a> unitsvalue,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;int xresvalue,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;int yresvalue<br>
+);</p>
+<h4 class="parameters">Parameters</h4>
+<dl>
+<dt>ipp</dt>
+<dd class="description">IPP message</dd>
+<dt>attr</dt>
+<dd class="description">IPP attribute</dd>
+<dt>element</dt>
+<dd class="description">Value number (0-based)</dd>
+<dt>unitsvalue</dt>
+<dd class="description">Resolution units</dd>
+<dt>xresvalue</dt>
+<dd class="description">Horizontal/cross feed resolution</dd>
+<dt>yresvalue</dt>
+<dd class="description">Vertical/feed resolution</dd>
+</dl>
+<h4 class="returnvalue">Return Value</h4>
+<p class="description">1 on success, 0 on failure</p>
+<h4 class="discussion">Discussion</h4>
+<p class="discussion">The <code>ipp</code> parameter refers to the IPP message containing the attribute that was
+previously created using the <a href="#ippNew"><code>ippNew</code></a> or <a href="#ippNewRequest"><code>ippNewRequest</code></a> functions.<br>
+<br>
+The <code>attr</code> parameter may be modified as a result of setting the value.<br>
+<br>
+The <code>element</code> parameter specifies which value to set from 0 to
+<a href="#ippGetCount(attr)"><code>ippGetCount(attr)</code></a>.
+
+</p>
+<h3 class="function"><span class="info">&nbsp;CUPS 1.6&nbsp;</span><a name="ippSetStatusCode">ippSetStatusCode</a></h3>
+<p class="description">Set the status code in an IPP response or event message.</p>
+<p class="code">
+int ippSetStatusCode (<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_t">ipp_t</a> *ipp,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;ipp_status_t status<br>
+);</p>
+<h4 class="parameters">Parameters</h4>
+<dl>
+<dt>ipp</dt>
+<dd class="description">IPP response or event message</dd>
+<dt>status</dt>
+<dd class="description">Status code</dd>
+</dl>
+<h4 class="returnvalue">Return Value</h4>
+<p class="description">1 on success, 0 on failure</p>
+<h4 class="discussion">Discussion</h4>
+<p class="discussion">The <code>ipp</code> parameter refers to an IPP message previously created using the
+<a href="#ippNew"><code>ippNew</code></a> or <a href="#ippNewRequest"><code>ippNewRequest</code></a> functions.
+
+</p>
+<h3 class="function"><span class="info">&nbsp;CUPS 1.6&nbsp;</span><a name="ippSetString">ippSetString</a></h3>
+<p class="description">Set a string value in an attribute.</p>
+<p class="code">
+int ippSetString (<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_t">ipp_t</a> *ipp,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_attribute_t">ipp_attribute_t</a> **attr,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;int element,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;const char *strvalue<br>
+);</p>
+<h4 class="parameters">Parameters</h4>
+<dl>
+<dt>ipp</dt>
+<dd class="description">IPP message</dd>
+<dt>attr</dt>
+<dd class="description">IPP attribute</dd>
+<dt>element</dt>
+<dd class="description">Value number (0-based)</dd>
+<dt>strvalue</dt>
+<dd class="description">String value</dd>
+</dl>
+<h4 class="returnvalue">Return Value</h4>
+<p class="description">1 on success, 0 on failure</p>
+<h4 class="discussion">Discussion</h4>
+<p class="discussion">The <code>ipp</code> parameter refers to the IPP message containing the attribute that was
+previously created using the <a href="#ippNew"><code>ippNew</code></a> or <a href="#ippNewRequest"><code>ippNewRequest</code></a> functions.<br>
+<br>
+The <code>attr</code> parameter may be modified as a result of setting the value.<br>
+<br>
+The <code>element</code> parameter specifies which value to set from 0 to
+<a href="#ippGetCount(attr)"><code>ippGetCount(attr)</code></a>.
+
+</p>
+<h3 class="function"><span class="info">&nbsp;CUPS 1.6&nbsp;</span><a name="ippSetValueTag">ippSetValueTag</a></h3>
+<p class="description">Set the value tag of an attribute.</p>
+<p class="code">
+int ippSetValueTag (<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_t">ipp_t</a> *ipp,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_attribute_t">ipp_attribute_t</a> **attr,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;ipp_tag_t value_tag<br>
+);</p>
+<h4 class="parameters">Parameters</h4>
+<dl>
+<dt>ipp</dt>
+<dd class="description">IPP message</dd>
+<dt>attr</dt>
+<dd class="description">IPP attribute</dd>
+<dt>value_tag</dt>
+<dd class="description">Value tag</dd>
+</dl>
+<h4 class="returnvalue">Return Value</h4>
+<p class="description">1 on success, 0 on failure</p>
+<h4 class="discussion">Discussion</h4>
+<p class="discussion">The <code>ipp</code> parameter refers to the IPP message containing the attribute that was
+previously created using the <a href="#ippNew"><code>ippNew</code></a> or <a href="#ippNewRequest"><code>ippNewRequest</code></a> functions.<br>
+<br>
+The <code>attr</code> parameter may be modified as a result of setting the value.<br>
+<br>
+Integer (<code>IPP_TAG_INTEGER</code>) values can be promoted to rangeOfInteger
+(<code>IPP_TAG_RANGE</code>) values, the various string tags can be promoted to name
+(<code>IPP_TAG_NAME</code>) or nameWithLanguage (<code>IPP_TAG_NAMELANG</code>) values, text
+(<code>IPP_TAG_TEXT</code>) values can be promoted to textWithLanguage
+(<code>IPP_TAG_TEXTLANG</code>) values, and all values can be demoted to the various
+out-of-band value tags such as no-value (<code>IPP_TAG_NOVALUE</code>). All other changes
+will be rejected.<br>
+<br>
+Promoting a string attribute to nameWithLanguage or textWithLanguage adds the language
+code in the &quot;attributes-natural-language&quot; attribute or, if not present, the language
+code for the current locale.
+
+</p>
+<h3 class="function"><span class="info">&nbsp;CUPS 1.6&nbsp;</span><a name="ippSetVersion">ippSetVersion</a></h3>
+<p class="description">Set the version number in an IPP message.</p>
+<p class="code">
+int ippSetVersion (<br>
+&nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_t">ipp_t</a> *ipp,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;int major,<br>
+&nbsp;&nbsp;&nbsp;&nbsp;int minor<br>
+);</p>
+<h4 class="parameters">Parameters</h4>
+<dl>
+<dt>ipp</dt>
+<dd class="description">IPP message</dd>
+<dt>major</dt>
+<dd class="description">Major version number (major.minor)</dd>
+<dt>minor</dt>
+<dd class="description">Minor version number (major.minor)</dd>
+</dl>
+<h4 class="returnvalue">Return Value</h4>
+<p class="description">1 on success, 0 on failure</p>
+<h4 class="discussion">Discussion</h4>
+<p class="discussion">The <code>ipp</code> parameter refers to an IPP message previously created using the
+<a href="#ippNew"><code>ippNew</code></a> or <a href="#ippNewRequest"><code>ippNewRequest</code></a> functions.<br>
+<br>
+The valid version numbers are currently 1.0, 1.1, 2.0, 2.1, and 2.2.
+
+</p>
+<h3 class="function"><span class="info">&nbsp;CUPS 1.4/Mac OS X 10.6&nbsp;</span><a name="ippTagString">ippTagString</a></h3>
+<p class="description">Return the tag name corresponding to a tag value.</p>
+<p class="code">
+const char *ippTagString (<br>
+&nbsp;&nbsp;&nbsp;&nbsp;ipp_tag_t tag<br>
+);</p>
+<h4 class="parameters">Parameters</h4>
+<dl>
+<dt>tag</dt>
+<dd class="description">Tag value</dd>
+</dl>
 <h4 class="returnvalue">Return Value</h4>
 <p class="description">Tag name</p>
 <h4 class="discussion">Discussion</h4>
@@ -3284,7 +4327,7 @@ const char *ippTagString (<br>
 <h3 class="function"><span class="info">&nbsp;CUPS 1.4/Mac OS X 10.6&nbsp;</span><a name="ippTagValue">ippTagValue</a></h3>
 <p class="description">Return the tag value corresponding to a tag name.</p>
 <p class="code">
-<a href="#ipp_tag_t">ipp_tag_t</a> ippTagValue (<br>
+ipp_tag_t ippTagValue (<br>
 &nbsp;&nbsp;&nbsp;&nbsp;const char *name<br>
 );</p>
 <h4 class="parameters">Parameters</h4>
@@ -3457,9 +4500,19 @@ typedef enum <a href="#http_uri_status_e">http_uri_status_e</a> http_uri_status_
 typedef enum <a href="#http_version_e">http_version_e</a> http_version_t;
 </p>
 <h3 class="typedef"><a name="ipp_attribute_t">ipp_attribute_t</a></h3>
-<p class="description">Attribute</p>
+<p class="description">IPP attribute</p>
 <p class="code">
-typedef struct <a href="#ipp_attribute_s">ipp_attribute_s</a> ipp_attribute_t;
+typedef struct _ipp_attribute_s ipp_attribute_t;
+</p>
+<h3 class="typedef"><a name="ipp_copycb_t">ipp_copycb_t</a></h3>
+<p class="description">Prototypes...</p>
+<p class="code">
+typedef int (*ipp_copycb_t)(void *context, <a href="#ipp_t">ipp_t</a> *dst, <a href="#ipp_attribute_t">ipp_attribute_t</a> *attr);
+</p>
+<h3 class="typedef"><a name="ipp_dstate_t">ipp_dstate_t</a></h3>
+<p class="description">Document states</p>
+<p class="code">
+typedef enum <a href="#ipp_dstate_e">ipp_dstate_e</a> ipp_dstate_t;
 </p>
 <h3 class="typedef"><a name="ipp_finish_t">ipp_finish_t</a></h3>
 <p class="description">Finishings</p>
@@ -3469,17 +4522,12 @@ typedef enum <a href="#ipp_finish_e">ipp_finish_e</a> ipp_finish_t;
 <h3 class="typedef"><span class="info">&nbsp;CUPS 1.2/Mac OS X 10.5&nbsp;</span><a name="ipp_iocb_t">ipp_iocb_t</a></h3>
 <p class="description">IPP IO Callback Function </p>
 <p class="code">
-typedef ssize_t (*ipp_iocb_t)(void *, <a href="#ipp_uchar_t">ipp_uchar_t</a> *, size_t);
+typedef ssize_t (*ipp_iocb_t)(void *context, <a href="#ipp_uchar_t">ipp_uchar_t</a> *buffer, size_t bytes);
 </p>
-<h3 class="typedef"><a name="ipp_jstate_t">ipp_jstate_t</a></h3>
-<p class="description">Job states</p>
+<h3 class="typedef"><a name="ipp_jcollate_t">ipp_jcollate_t</a></h3>
+<p class="description">Job collation types</p>
 <p class="code">
-typedef enum <a href="#ipp_jstate_e">ipp_jstate_e</a> ipp_jstate_t;
-</p>
-<h3 class="typedef"><a name="ipp_op_t">ipp_op_t</a></h3>
-<p class="description">IPP operations</p>
-<p class="code">
-typedef enum <a href="#ipp_op_e">ipp_op_e</a> ipp_op_t;
+typedef enum <a href="#ipp_jcollate_e">ipp_jcollate_e</a> ipp_jcollate_t;
 </p>
 <h3 class="typedef"><a name="ipp_orient_t">ipp_orient_t</a></h3>
 <p class="description">Orientation values</p>
@@ -3496,11 +4544,6 @@ typedef enum <a href="#ipp_pstate_e">ipp_pstate_e</a> ipp_pstate_t;
 <p class="code">
 typedef enum <a href="#ipp_quality_e">ipp_quality_e</a> ipp_quality_t;
 </p>
-<h3 class="typedef"><a name="ipp_request_t">ipp_request_t</a></h3>
-<p class="description">Request Header</p>
-<p class="code">
-typedef union <a href="#ipp_request_u">ipp_request_u</a> ipp_request_t;
-</p>
 <h3 class="typedef"><a name="ipp_res_t">ipp_res_t</a></h3>
 <p class="description">Resolution units</p>
 <p class="code">
@@ -3512,24 +4555,14 @@ typedef enum <a href="#ipp_res_e">ipp_res_e</a> ipp_res_t;
 typedef enum <a href="#ipp_state_e">ipp_state_e</a> ipp_state_t;
 </p>
 <h3 class="typedef"><a name="ipp_t">ipp_t</a></h3>
-<p class="description">Attribute Value</p>
+<p class="description">IPP request/response data</p>
 <p class="code">
-typedef struct <a href="#ipp_s">ipp_s</a> ipp_t;
+typedef struct _ipp_s ipp_t;
 </p>
 <h3 class="typedef"><a name="ipp_uchar_t">ipp_uchar_t</a></h3>
-<p class="description">IPP status codes</p>
-<p class="code">
-typedef typedef unsigned char ipp_uchar_t;
-</p>
-<h3 class="typedef"><a name="ipp_tag_t">ipp_tag_t</a></h3>
-<p class="description">Format tags for attributes</p>
-<p class="code">
-typedef enum <a href="#ipp_tag_e">ipp_tag_e</a> ipp_tag_t;
-</p>
-<h3 class="typedef"><a name="ipp_value_t">ipp_value_t</a></h3>
-<p class="description">Attribute Value</p>
+<p class="description">Unsigned 8-bit integer/character</p>
 <p class="code">
-typedef union <a href="#ipp_value_u">ipp_value_u</a> ipp_value_t;
+typedef unsigned char ipp_uchar_t;
 </p>
 <h2 class="title"><a name="STRUCTURES">Structures</a></h2>
 <h3 class="struct"><a name="gss_auth_identity">gss_auth_identity</a></h3>
@@ -3580,86 +4613,6 @@ with a hostname. </p>
 <dt>datalen </dt>
 <dd class="description">Credential length</dd>
 </dl>
-<h3 class="struct"><a name="ipp_attribute_s">ipp_attribute_s</a></h3>
-<p class="description">Attribute</p>
-<p class="code">struct ipp_attribute_s {<br>
-&nbsp;&nbsp;&nbsp;&nbsp;char *name;<br>
-&nbsp;&nbsp;&nbsp;&nbsp;struct <a href="#ipp_attribute_s">ipp_attribute_s</a> *next;<br>
-&nbsp;&nbsp;&nbsp;&nbsp;int num_values;<br>
-&nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_tag_t">ipp_tag_t</a> group_tag, value_tag;<br>
-&nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_value_t">ipp_value_t</a> values[1];<br>
-};</p>
-<h4 class="members">Members</h4>
-<dl>
-<dt>name </dt>
-<dd class="description">Name of attribute</dd>
-<dt>next </dt>
-<dd class="description">Next attribute in list</dd>
-<dt>num_values </dt>
-<dd class="description">Number of values</dd>
-<dt>value_tag </dt>
-<dd class="description">What type of value is it?</dd>
-<dt>values[1] </dt>
-<dd class="description">Values</dd>
-</dl>
-<h3 class="struct"><a name="ipp_s">ipp_s</a></h3>
-<p class="description">IPP Request/Response/Notification</p>
-<p class="code">struct ipp_s {<br>
-&nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_attribute_t">ipp_attribute_t</a> *attrs;<br>
-&nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_attribute_t">ipp_attribute_t</a> *current;<br>
-&nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_tag_t">ipp_tag_t</a> curtag;<br>
-&nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_attribute_t">ipp_attribute_t</a> *last;<br>
-&nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_attribute_t">ipp_attribute_t</a> *prev;<br>
-&nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_request_t">ipp_request_t</a> request;<br>
-&nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_state_t">ipp_state_t</a> state;<br>
-&nbsp;&nbsp;&nbsp;&nbsp;int use;<br>
-};</p>
-<h4 class="members">Members</h4>
-<dl>
-<dt>attrs </dt>
-<dd class="description">Attributes</dd>
-<dt>current </dt>
-<dd class="description">Current attribute (for read/write)</dd>
-<dt>curtag </dt>
-<dd class="description">Current attribute group tag</dd>
-<dt>last </dt>
-<dd class="description">Last attribute in list</dd>
-<dt>prev <span class="info">&nbsp;CUPS 1.2/Mac OS X 10.5&nbsp;</span></dt>
-<dd class="description">Previous attribute (for read) </dd>
-<dt>request </dt>
-<dd class="description">Request header</dd>
-<dt>state </dt>
-<dd class="description">State of request</dd>
-<dt>use <span class="info">&nbsp;CUPS 1.4.4/Mac OS X 10.6.?&nbsp;</span></dt>
-<dd class="description">Use count </dd>
-</dl>
-<h2 class="title"><a name="UNIONS">Unions</a></h2>
-<h3 class="union"><a name="ipp_request_u">ipp_request_u</a></h3>
-<p class="description">Request Header</p>
-<p class="code">union ipp_request_u {<br>
-};</p>
-<h4 class="members">Members</h4>
-<dl>
-</dl>
-<h3 class="union"><a name="ipp_value_u">ipp_value_u</a></h3>
-<p class="description">Attribute Value</p>
-<p class="code">union ipp_value_u {<br>
-&nbsp;&nbsp;&nbsp;&nbsp;char boolean;<br>
-&nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_t">ipp_t</a> *collection;<br>
-&nbsp;&nbsp;&nbsp;&nbsp;<a href="#ipp_uchar_t">ipp_uchar_t</a> date[11];<br>
-&nbsp;&nbsp;&nbsp;&nbsp;int integer;<br>
-};</p>
-<h4 class="members">Members</h4>
-<dl>
-<dt>boolean </dt>
-<dd class="description">Boolean value</dd>
-<dt>collection <span class="info">&nbsp;CUPS 1.1.19/Mac OS X 10.3&nbsp;</span></dt>
-<dd class="description">Collection value </dd>
-<dt>date[11] </dt>
-<dd class="description">Date/time value</dd>
-<dt>integer </dt>
-<dd class="description">Integer/enumerated value</dd>
-</dl>
 <h2 class="title"><a name="ENUMERATIONS">Constants</a></h2>
 <h3 class="enumeration"><a name="http_auth_e">http_auth_e</a></h3>
 <p class="description">HTTP authentication types</p>
@@ -3960,6 +4913,16 @@ are server-oriented...</p>
 <dt>HTTP_1_1 </dt>
 <dd class="description">HTTP/1.1</dd>
 </dl>
+<h3 class="enumeration"><a name="ipp_dstate_e">ipp_dstate_e</a></h3>
+<p class="description">Document states</p>
+<h4 class="constants">Constants</h4>
+<dl>
+<dt>IPP_DOCUMENT_ABORTED </dt>
+<dt>IPP_DOCUMENT_CANCELED </dt>
+<dt>IPP_DOCUMENT_COMPLETED </dt>
+<dt>IPP_DOCUMENT_PENDING </dt>
+<dt>IPP_DOCUMENT_PROCESSING </dt>
+</dl>
 <h3 class="enumeration"><a name="ipp_finish_e">ipp_finish_e</a></h3>
 <p class="description">Finishings</p>
 <h4 class="constants">Constants</h4>
@@ -4020,6 +4983,22 @@ are server-oriented...</p>
 <dd class="description">Staple top right corner</dd>
 <dt>IPP_FINISHINGS_TRIM </dt>
 <dd class="description">Trim (any type)</dd>
+<dt>IPP_FINISHINGS_TRIM_AFTER_COPIES </dt>
+<dd class="description">Trim output after each copy</dd>
+<dt>IPP_FINISHINGS_TRIM_AFTER_DOCUMENTS </dt>
+<dd class="description">Trim output after each document</dd>
+<dt>IPP_FINISHINGS_TRIM_AFTER_JOB </dt>
+<dd class="description">Trim output after job</dd>
+<dt>IPP_FINISHINGS_TRIM_AFTER_PAGES </dt>
+<dd class="description">Trim output after each page</dd>
+</dl>
+<h3 class="enumeration"><a name="ipp_jcollate_e">ipp_jcollate_e</a></h3>
+<p class="description">Job collation types</p>
+<h4 class="constants">Constants</h4>
+<dl>
+<dt>IPP_JOB_COLLATED_DOCUMENTS </dt>
+<dt>IPP_JOB_UNCOLLATED_DOCUMENTS </dt>
+<dt>IPP_JOB_UNCOLLATED_SHEETS </dt>
 </dl>
 <h3 class="enumeration"><a name="ipp_jstate_e">ipp_jstate_e</a></h3>
 <p class="description">Job states</p>
@@ -4112,6 +5091,8 @@ are server-oriented...</p>
 <dd class="description">Get subscription attributes </dd>
 <dt>IPP_HOLD_JOB </dt>
 <dd class="description">Hold a job for printing</dd>
+<dt>IPP_IDENTIFY_PRINTER </dt>
+<dd class="description">Identify-Printer (proposed IPP JPS3)</dd>
 <dt>IPP_PAUSE_PRINTER </dt>
 <dd class="description">Stop a printer</dd>
 <dt>IPP_PRINT_JOB </dt>
@@ -4224,14 +5205,20 @@ are server-oriented...</p>
 <dd class="description">client-error-document-format-not-supported</dd>
 <dt>IPP_DOCUMENT_FORMAT_ERROR </dt>
 <dd class="description">client-error-document-format-error</dd>
+<dt>IPP_DOCUMENT_PASSWORD_ERROR </dt>
+<dd class="description">client-error-document-password-error</dd>
+<dt>IPP_DOCUMENT_PERMISSION_ERROR </dt>
+<dd class="description">client-error-document-permission-error</dd>
+<dt>IPP_DOCUMENT_SECURITY_ERROR </dt>
+<dd class="description">client-error-document-security-error</dd>
+<dt>IPP_DOCUMENT_UNPRINTABLE_ERROR </dt>
+<dd class="description">client-error-document-unprintable-error</dd>
 <dt>IPP_ERROR_JOB_CANCELED </dt>
 <dd class="description">server-error-job-canceled</dd>
 <dt>IPP_FORBIDDEN </dt>
 <dd class="description">client-error-forbidden</dd>
 <dt>IPP_GONE </dt>
 <dd class="description">client-error-gone</dd>
-<dt>IPP_IGNORED_ALL_NOTIFICATIONS </dt>
-<dd class="description">client-error-ignored-all-notifications</dd>
 <dt>IPP_IGNORED_ALL_SUBSCRIPTIONS </dt>
 <dd class="description">client-error-ignored-all-subscriptions</dd>
 <dt>IPP_INTERNAL_ERROR </dt>
@@ -4250,14 +5237,10 @@ are server-oriented...</p>
 <dd class="description">client-error-not-possible</dd>
 <dt>IPP_OK </dt>
 <dd class="description">successful-ok</dd>
-<dt>IPP_OK_BUT_CANCEL_SUBSCRIPTION </dt>
-<dd class="description">successful-ok-but-cancel-subscription</dd>
 <dt>IPP_OK_CONFLICT </dt>
 <dd class="description">successful-ok-conflicting-attributes</dd>
 <dt>IPP_OK_EVENTS_COMPLETE </dt>
 <dd class="description">successful-ok-events-complete</dd>
-<dt>IPP_OK_IGNORED_NOTIFICATIONS </dt>
-<dd class="description">successful-ok-ignored-notifications</dd>
 <dt>IPP_OK_IGNORED_SUBSCRIPTIONS </dt>
 <dd class="description">successful-ok-ignored-subscriptions</dd>
 <dt>IPP_OK_SUBST </dt>
@@ -4272,8 +5255,6 @@ are server-oriented...</p>
 <dd class="description">server-error-busy</dd>
 <dt>IPP_PRINTER_IS_DEACTIVATED </dt>
 <dd class="description">server-error-printer-is-deactivated</dd>
-<dt>IPP_PRINT_SUPPORT_FILE_NOT_FOUND </dt>
-<dd class="description">client-error-print-support-file-not-found</dd>
 <dt>IPP_REQUEST_ENTITY </dt>
 <dd class="description">client-error-request-entity-too-large</dd>
 <dt>IPP_REQUEST_VALUE </dt>
@@ -4305,14 +5286,14 @@ are server-oriented...</p>
 <dd class="description">Boolean value</dd>
 <dt>IPP_TAG_CHARSET </dt>
 <dd class="description">Character set value</dd>
-<dt>IPP_TAG_COPY </dt>
-<dd class="description">Bitflag for copied attribute values</dd>
 <dt>IPP_TAG_DATE </dt>
 <dd class="description">Date/time value</dd>
 <dt>IPP_TAG_DEFAULT </dt>
 <dd class="description">Default value</dd>
 <dt>IPP_TAG_DELETEATTR </dt>
 <dd class="description">Delete-attribute value</dd>
+<dt>IPP_TAG_DOCUMENT </dt>
+<dd class="description">Document group</dd>
 <dt>IPP_TAG_END </dt>
 <dd class="description">End-of-attributes</dd>
 <dt>IPP_TAG_END_COLLECTION </dt>
@@ -4321,6 +5302,8 @@ are server-oriented...</p>
 <dd class="description">Enumeration value</dd>
 <dt>IPP_TAG_EVENT_NOTIFICATION </dt>
 <dd class="description">Event group</dd>
+<dt>IPP_TAG_EXTENSION </dt>
+<dd class="description">Extension point for 32-bit tags</dd>
 <dt>IPP_TAG_INTEGER </dt>
 <dd class="description">Integer value</dd>
 <dt>IPP_TAG_JOB </dt>
@@ -4329,8 +5312,6 @@ are server-oriented...</p>
 <dd class="description">Keyword value</dd>
 <dt>IPP_TAG_LANGUAGE </dt>
 <dd class="description">Language value</dd>
-<dt>IPP_TAG_MASK </dt>
-<dd class="description">Mask for copied attribute values</dd>
 <dt>IPP_TAG_MEMBERNAME </dt>
 <dd class="description">Collection member name value</dd>
 <dt>IPP_TAG_MIMETYPE </dt>
index c7b7a61195de09ca44db747d976f929afdd9d803..5746406920a2d90ab4ec402f7f019e603ded98d0 100644 (file)
@@ -2,7 +2,7 @@
 <html>
 <!-- SECTION: Programming -->
 <head>
-       <title>PPD API  </title>
+       <title>PPD API (DEPRECATED)     </title>
        <meta name="keywords" content="Programming">
        <meta http-equiv="Content-Type" content="text/html;charset=utf-8">
        <meta name="creator" content="Mini-XML v2.7">
@@ -354,7 +354,9 @@ div.contents ul.subcontents li {
   file is missing or damaged, see the license at "http://www.cups.org/".
 -->
 
-<h1 class='title'>PPD API</h1>
+<h1 class='title'>PPD API (DEPRECATED)</h1>
+
+<blockquote>The PPD API is deprecated starting in CUPS 1.6. Please use the new Job Ticket APIs in the <a href="api-cups.html">CUPS API</a> documentation. These functions will be removed in a future release of CUPS.</blockquote>
 
 <div class='summary'><table summary='General Information'>
 <thead>
@@ -500,6 +502,8 @@ conflicts.">ppdMarkOption</a></li>
 
 <h2 class='title'><a name='OVERVIEW'>Overview</a></h2>
 
+<blockquote>The PPD API is deprecated starting in CUPS 1.6. Please use the new Job Ticket APIs in the <a href="api-cups.html">CUPS API</a> documentation. These functions will be removed in a future release of CUPS.</blockquote>
+
 <p>The CUPS PPD API provides read-only access the data in PostScript Printer
 Description ("PPD") files which are used for all printers with a driver. With
 it you can obtain the data necessary to display printer options to users, mark
diff --git a/doc/help/man-ipptool.html b/doc/help/man-ipptool.html
new file mode 100644 (file)
index 0000000..ce09095
--- /dev/null
@@ -0,0 +1,144 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<!-- SECTION: Man Pages -->
+<head>
+       <link rel="stylesheet" type="text/css" href="../cups-printable.css">
+       <title>ipptool(1)</title>
+</head>
+<body>
+<h1 class="title">ipptool(1)</h1>
+<h2 class="title"><a name="NAME">Name</a></h2>
+ipptool - perform internet printing protocol requests
+<h2 class="title"><a name="SYNOPSIS">Synopsis</a></h2>
+<b>ipptool
+</b>[ -4 ] [ -6 ] [ -C ] [ -E ] [ -I ] [ -L ] [ -S ] [ -T
+<i>seconds
+</i>] [ -V
+<i>version
+</i>] [ -X ] [ -c ] [ -d
+<i>name=value
+</i>] [ -f
+<i>filename
+</i>] [ -i
+<i>seconds
+</i>] [ -n
+<i>repeat-count
+</i>] [ -q ] [ -t ] [ -v ]
+<i>URI
+</i><i>filename
+</i>[
+<i>... filenameN
+</i>]
+<h2 class="title"><a name="DESCRIPTION">Description</a></h2>
+<i>ipptool</i> sends IPP requests to the specified URI and tests and/or displays the results. Each named file defines one or more requests, including the expected response status, attributes, and values. Output is either a plain text, formatted text, CSV, or XML report on the standard output, with a non-zero exit status indicating that one or more tests have failed. The file format is described in <a href='man-ipptoolfile.html?TOPIC=Man+Pages'>ipptoolfile(5)</a>.
+<h2 class="title"><a name="OPTIONS">Options</a></h2>
+The following options are recognized by <i>ipptool</i>:
+<dl>
+<dt>-4
+</dt>
+<dd>Specifies that <i>ipptool</i> must connect to the printer or server using IPv4.
+</dd>
+<dt>-6
+</dt>
+<dd>Specifies that <i>ipptool</i> must connect to the printer or server using IPv6.
+</dd>
+<dt>-C
+</dt>
+<dd>Specifies that requests should be sent using the HTTP/1.1 "Transfer-Encoding: chunked" header, which is required for conformance by all versions of IPP. The default is to use "Transfer-Encoding: chunked" for requests with attached files and "Content-Length:" for requests without attached files.
+</dd>
+<dt>-E
+</dt>
+<dd>Forces TLS encryption when connecting to the server using the HTTP "Upgrade" header.
+</dd>
+<dt>-I
+</dt>
+<dd>Specifies that <i>ipptool</i> will continue past errors.
+</dd>
+<dt>-L
+</dt>
+<dd>Specifies that requests should be sent using the HTTP/1.0 "Content-Length:" header, which is required for conformance by all versions of IPP. The default is to use "Transfer-Encoding: chunked" for requests with attached files and "Content-Length:" for requests without attached files.
+</dd>
+<dt>-S
+</dt>
+<dd>Forces (dedicated) SSL encryption when connecting to the server.
+</dd>
+<dt>-T seconds
+</dt>
+<dd>Specifies a timeout for IPP requests in seconds.
+</dd>
+<dt>-V version
+</dt>
+<dd>Specifies the default IPP version to use: 1.0, 1.1, 2.0, 2.1, or 2.2. If not specified, version 1.1 is used.
+</dd>
+<dt>-X
+</dt>
+<dd>Specifies that XML (Apple plist) output is desired instead of the plain text report. This option is incompatible with the <i>-i</i> (interval) and <i>-n</i> (repeat-count) options.
+</dd>
+<dt>-c
+</dt>
+<dd>Specifies that CSV (comma-separated values) output is desired instead of the plain text output.
+</dd>
+<dt>-d name=value
+</dt>
+<dd>Defines the named variable.
+</dd>
+<dt>-f filename
+</dt>
+<dd>Defines the default request filename for tests.
+</dd>
+<dt>-i seconds
+</dt>
+<dd>Specifies that the (last) file should be repeated at the specified interval. This option is incompatible with the <i>-X</i> (XML plist output) option.
+</dd>
+<dt>-l
+</dt>
+<dd>Specifies that plain text output is desired.
+</dd>
+<dt>-n repeat-count
+</dt>
+<dd>Specifies that the (last) file should be repeated the specified number of times. This option is incompatible with the <i>-X</i> (XML plist output) option.
+</dd>
+<dt>-t
+</dt>
+<dd>Specifies that CUPS test report output is desired instead of the plain text output.
+</dd>
+<dt>-v
+</dt>
+<dd>Specifies that all request and response attributes should be output in CUPS test mode (<i>-t</i>). This is the default for XML output.
+</dd>
+</dl>
+<h2 class="title"><a name="COMPATIBILITY">Compatibility</a></h2>
+The <i>ipptool</i> program is unique to CUPS.
+<h2 class="title"><a name="EXAMPLES">Examples</a></h2>
+Get a list of completed jobs for "myprinter":
+<pre>
+    ipptool ipp://localhost/printers/myprinter get-completed-jobs.test
+</pre>
+<p>Send email notifications to "user@example.com" when "myprinter" changes:
+<pre>
+    ipptool -d recipient=mailto:user@example.com 
+        ipp://localhost/printers/myprinter create-printer-subscription.test
+</pre>
+<h2 class="title"><a name="STANDARD_FILES">Standard Files</a></h2>
+The following standard files are available:
+<pre>
+    create-printer-subscription.test
+    get-completed-jobs.test
+    get-jobs.test
+    ipp-1.1.test
+    ipp-2.0.test
+    ipp-2.1.test
+    testfile.jpg
+    testfile.pdf
+    testfile.ps
+    testfile.txt
+</pre>
+<h2 class="title"><a name="SEE_ALSO">See Also</a></h2>
+<a href='man-ipptoolfile.html?TOPIC=Man+Pages'>ipptoolfile(5)</a>,
+<br>
+<a href='http://localhost:631/help'>http://localhost:631/help</a>
+<h2 class="title"><a name="COPYRIGHT">Copyright</a></h2>
+Copyright 2007-2010 by Apple Inc.
+
+</body>
+</html>
diff --git a/doc/help/man-ipptoolfile.html b/doc/help/man-ipptoolfile.html
new file mode 100644 (file)
index 0000000..baab6fe
--- /dev/null
@@ -0,0 +1,607 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<!-- SECTION: Man Pages -->
+<head>
+       <link rel="stylesheet" type="text/css" href="../cups-printable.css">
+       <title>ipptoolfile(5)</title>
+</head>
+<body>
+<h1 class="title">ipptoolfile(5)</h1>
+<h2 class="title"><a name="NAME">Name</a></h2>
+ipptoolfile - ipptool file format
+
+<h2 class="title"><a name="DESCRIPTION">Description</a></h2>
+The <a href='man-ipptool.html?TOPIC=Man+Pages'>ipptool(1)</a> program accepts free-form plain text files that describe one or more IPP requests. Comments start with the "#" character and continue to the end of the line. Each request is enclosed by curley braces, for example:
+<pre>
+
+    # This is a comment
+    {
+      # The name of the test
+      NAME "Print PostScript Job"
+
+      # The request to send
+      OPERATION Print-Job
+      GROUP operation-attributes-tag
+      ATTR charset attributes-charset utf-8
+      ATTR language attributes-natural-language en
+      ATTR uri printer-uri $uri
+      ATTR name requesting-user-name $user
+      FILE testfile.ps
+
+      # The response to expect
+      STATUS successful-ok
+      EXPECT attributes-charset OF-TYPE charset
+      EXPECT attributes-natural-language OF-TYPE naturalLanguage
+      EXPECT job-id OF-TYPE integer
+      EXPECT job-uri OF-TYPE uri
+    }
+    {
+      # The name of the test
+      NAME "Get Attributes of PostScript Job"
+
+      # The request to send
+      OPERATION Get-Job-Attributes
+      GROUP operation-attributes-tag
+      ATTR charset attributes-charset utf-8
+      ATTR language attributes-natural-language en
+      ATTR uri printer-uri $uri
+      ATTR integer job-id $job-id
+      ATTR name requesting-user-name $user
+
+      # The response to expect
+      STATUS successful-ok
+      EXPECT attributes-charset OF-TYPE charset
+      EXPECT attributes-natural-language OF-TYPE naturalLanguage
+      EXPECT job-id OF-TYPE integer
+      EXPECT job-uri OF-TYPE uri
+      EXPECT job-state OF-TYPE enum
+      EXPECT job-originating-user-name OF-TYPE name WITH-VALUE "$user"
+    }
+</pre>
+
+<h2 class="title"><a name="TOP-LEVEL_DIRECTIVES">Top-level Directives</a></h2>
+The following directives can be used outside of a test:
+<dl>
+<dt>{ test }
+</dt>
+<dd>Defines a test.
+</dd>
+<dt>DEFINE variable-name value
+</dt>
+<dd>Defines the named variable to the given value. This is equivalent to specifying
+"-d variable-name=value" on the <i>ipptool</i> command-line.
+</dd>
+<dt>DEFINE-DEFAULT variable-name value
+</dt>
+<dd>Defines the named variable to the given value if it does not already have a
+value.
+</dd>
+<dt>IGNORE-ERRORS yes
+</dt>
+<dd></dd>
+<dt>IGNORE-ERRORS no
+</dt>
+<dd>Specifies whether, by default, <i>ipptool</i> will ignore errors and continue with
+subsequent tests.
+</dd>
+<dt>INCLUDE "filename"
+</dt>
+<dd></dd>
+<dt>INCLUDE &lt;filename>
+</dt>
+<dd>Includes another test file. The first form includes a file relative to the
+current test file, while the second form includes a file from the <i>ipptool</i>
+include directory.
+</dd>
+<dt>INCLUDE-IF-DEFINED name "filename"
+</dt>
+<dd></dd>
+<dt>INCLUDE-IF-DEFINED name &lt;filename>
+</dt>
+<dd>Includes another test file if the named variable is defined. The first form
+includes a file relative to the current test file, while the second form
+includes a file from the <i>ipptool</i> include directory.
+</dd>
+<dt>INCLUDE-IF-NOT-DEFINED name "filename"
+</dt>
+<dd></dd>
+<dt>INCLUDE-IF-NOT-DEFINED name &lt;filename>
+</dt>
+<dd>Includes another test file if the named variable is not defined. The first form
+includes a file relative to the current test file, while the second form
+includes a file from the <i>ipptool</i> include directory.
+</dd>
+<dt>SKIP-IF-DEFINED variable-name
+</dt>
+<dd></dd>
+<dt>SKIP-IF-NOT-DEFINED variable-name
+</dt>
+<dd>Specifies that the remainder of the test file should be skipped when the
+variable is or is not defined.
+</dd>
+<dt>TRANSFER auto
+</dt>
+<dd>Specifies that tests will, by default, use "Transfer-Encoding: chunked" for
+requests with attached files and "Content-Length:" for requests without attached
+files.
+</dd>
+<dt>TRANSFER chunked
+</dt>
+<dd>Specifies that tests will, by default, use the HTTP/1.1 "Transfer-Encoding:
+chunked" header. This is the default and is equivalent to specifying "-c" on the
+<i>ipptool</i> command-line. Support for chunked requests is required for
+conformance with all versions of IPP.
+</dd>
+<dt>TRANSFER length
+</dt>
+<dd>Specifies that tests will, by default, use the HTTP/1.0 "Content-Length:"
+header. This is equivalent to specifying "-l" on the <i>ipptool</i> command-line.
+Support for content length requests is required for conformance with all
+versions of IPP.
+</dd>
+<dt>VERSION 1.0
+</dt>
+<dd></dd>
+<dt>VERSION 1.1
+</dt>
+<dd></dd>
+<dt>VERSION 2.0
+</dt>
+<dd></dd>
+<dt>VERSION 2.1
+</dt>
+<dd></dd>
+<dt>VERSION 2.2
+</dt>
+<dd>Specifies the default IPP version number to use for the tests that follow.
+
+</dd>
+</dl>
+<h2 class="title"><a name="TEST_DIRECTIVES">Test Directives</a></h2>
+The following directives are understood in a test:
+<dl>
+<dt>ATTR tag attribute-name value(s)
+</dt>
+<dd>Adds an attribute to the test request. Values are separated by the comma (",")
+character - escape commas using the "" character.
+</dd>
+<dt>ATTR collection attribute-name { MEMBER tag member-name value(s) ... } [ ... { ... } ]
+</dt>
+<dd>Adds a collection attribute to the test request. Member attributes follow the
+same syntax as regular attributes and can themselves be nested collections.
+Multiple collection values can be supplied as needed.
+</dd>
+<dt>DELAY seconds
+</dt>
+<dd>Specifies a delay before this test will be run.
+</dd>
+<dt>DISPLAY attribute-name
+</dt>
+<dd>Specifies that value of the named attribute should be output as part of the
+test report.
+</dd>
+<dt>EXPECT attribute-name [ predicate(s) ]
+</dt>
+<dd></dd>
+<dt>EXPECT ?attribute-name predicate(s)
+</dt>
+<dd></dd>
+<dt>EXPECT !attribute-name
+</dt>
+<dd>Specifies that the response must/may/must not include the named attribute.
+Additional requirements can be added as predicates - see the "EXPECT PREDICATES"
+section for more information on predicates.
+</dd>
+<dt>FILE filename
+</dt>
+<dd>Specifies a file to include at the end of the request. This is typically used
+when sending a test print file.
+</dd>
+<dt>GROUP tag
+</dt>
+<dd>Specifies the group tag for subsequent attributes in the request.
+</dd>
+<dt>IGNORE-ERRORS yes
+</dt>
+<dd></dd>
+<dt>IGNORE-ERRORS no
+</dt>
+<dd>Specifies whether <i>ipptool</i> will ignore errors and continue with subsequent
+tests.
+</dd>
+<dt>NAME "literal string"
+</dt>
+<dd>Specifies the human-readable name of the test.
+</dd>
+<dt>OPERATION operation-code
+</dt>
+<dd>Specifies the operation to be performed.
+</dd>
+<dt>REQUEST-ID number
+</dt>
+<dd></dd>
+<dt>REQUEST-ID random
+</dt>
+<dd>Specifies the request-id value to use in the request, either an integer or the
+word "random" to use a randomly generated value (the default).
+</dd>
+<dt>RESOURCE path
+</dt>
+<dd>Specifies an alternate resource path that is used for the HTTP POST request.
+The default is the resource from the URI provided to the <i>ipptool</i> program.
+</dd>
+<dt>SKIP-IF-DEFINED variable-name
+</dt>
+<dd></dd>
+<dt>SKIP-IF-NOT-DEFINED variable-name
+</dt>
+<dd>Specifies that the current test should be skipped when the variable is or is not
+defined.
+</dd>
+<dt>SKIP-PREVIOUS-ERROR yes
+</dt>
+<dd></dd>
+<dt>SKIP-PREVIOUS-ERROR no
+</dt>
+<dd>Specifies whether <i>ipptool</i> will skip the current test if the previous test
+resulted in an error/failure.
+</dd>
+<dt>STATUS status-code [ predicate ]
+</dt>
+<dd>Specifies an expected response status-code value. Additional requirements can be
+added as predicates - see the "STATUS PREDICATES" section for more information
+on predicates.
+</dd>
+<dt>TRANSFER auto
+</dt>
+<dd>Specifies that this test will use "Transfer-Encoding: chunked" if it has an
+attached file or "Content-Length:" otherwise.
+</dd>
+<dt>TRANSFER chunked
+</dt>
+<dd>Specifies that this test will use the HTTP/1.1 "Transfer-Encoding: chunked"
+header.
+</dd>
+<dt>TRANSFER length
+</dt>
+<dd>Specifies that this test will use the HTTP/1.0 "Content-Length:" header.
+</dd>
+<dt>VERSION 1.0
+</dt>
+<dd></dd>
+<dt>VERSION 1.1
+</dt>
+<dd></dd>
+<dt>VERSION 2.0
+</dt>
+<dd></dd>
+<dt>VERSION 2.1
+</dt>
+<dd></dd>
+<dt>VERSION 2.2
+</dt>
+<dd>Specifies the IPP version number to use for this test.
+
+</dd>
+</dl>
+<h2 class="title"><a name="EXPECT_PREDICATES">Expect Predicates</a></h2>
+The following predicates are understood following the EXPECT test directive:
+<dl>
+<dt>COUNT number
+</dt>
+<dd>Requires the EXPECT attribute to have the specified number of values.
+</dd>
+<dt>DEFINE-MATCH variable-name
+</dt>
+<dd>Defines the variable to "1" when the EXPECT condition matches. A side-effect of
+this predicate is that this EXPECT will never fail a test.
+</dd>
+<dt>DEFINE-NO-MATCH variable-name
+</dt>
+<dd>Defines the variable to "1" when the EXPECT condition does not match. A side-
+effect of this predicate is that this EXPECT will never fail a test.
+</dd>
+<dt>DEFINE-VALUE variable-name
+</dt>
+<dd>Defines the variable to the value of the attribute when the EXPECT condition
+matches. A side-effect of this predicate is that this EXPECT will never fail a test.
+</dd>
+<dt>IF-DEFINED variable-name
+</dt>
+<dd>Makes the EXPECT conditions apply only if the specified variable is defined.
+</dd>
+<dt>IF-NOT-DEFINED variable-name
+</dt>
+<dd>Makes the EXPECT conditions apply only if the specified variable is not
+defined.
+</dd>
+<dt>IN-GROUP tag
+</dt>
+<dd>Requires the EXPECT attribute to be in the specified group tag.
+</dd>
+<dt>OF-TYPE tag[,tag,...]
+</dt>
+<dd>Requires the EXPECT attribute to use the specified value tag(s).
+</dd>
+<dt>REPEAT-MATCH
+</dt>
+<dd></dd>
+<dt>REPEAT-NO-MATCH
+</dt>
+<dd>Specifies that the current test should be repeated when the EXPECT condition
+matches or does not match.
+</dd>
+<dt>SAME-COUNT-AS attribute-name
+</dt>
+<dd>Requires the EXPECT attribute to have the same number of values as the specified
+parallel attribute.
+</dd>
+<dt>WITH-VALUE "literal string"
+</dt>
+<dd>Requires at least one value of the EXPECT attribute to match the literal string.
+Comparisons are case-sensitive.
+</dd>
+<dt>WITH-VALUE "/regular expression/"
+</dt>
+<dd>Requires that all values of the EXPECT attribute match the regular expression,
+which must conform to the POSIX regular expression syntax.
+Comparisons are case-sensitive.
+
+</dd>
+</dl>
+<h2 class="title"><a name="STATUS_PREDICATES">Status Predicates</a></h2>
+The following predicates are understood following the STATUS test directive:
+<dl>
+<dt>IF-DEFINED variable-name
+</dt>
+<dd>Makes the STATUS apply only if the specified variable is defined.
+</dd>
+<dt>IF-NOT-DEFINED variable-name
+</dt>
+<dd>Makes the STATUS apply only if the specified variable is not defined.
+</dd>
+<dt>REPEAT-MATCH
+</dt>
+<dd></dd>
+<dt>REPEAT-NO-MATCH
+</dt>
+<dd>Specifies that the current test should be repeated when the response status-code
+matches or does not match the value specified by the STATUS directive.
+
+</dd>
+</dl>
+<h2 class="title"><a name="OPERATION_CODES">Operation Codes</a></h2>
+Operation codes correspond to the hexadecimal numbers (0xHHHH) and names from
+RFC 2911 and other IPP extension specifications. Here is a complete list:
+<pre>
+    Activate-Printer
+    CUPS-Accept-Jobs
+    CUPS-Add-Modify-Class
+    CUPS-Add-Modify-Printer
+    CUPS-Authenticate-Job
+    CUPS-Delete-Class
+    CUPS-Delete-Printer
+    CUPS-Get-Classes
+    CUPS-Get-Default
+    CUPS-Get-Devices
+    CUPS-Get-Document
+    CUPS-Get-PPD
+    CUPS-Get-PPDs
+    CUPS-Get-Printers
+    CUPS-Move-Job
+    CUPS-Reject-Jobs
+    CUPS-Set-Default
+    Cancel-Current-Job
+    Cancel-Job
+    Cancel-Jobs
+    Cancel-My-Jobs
+    Cancel-Subscription
+    Close-Job
+    Create-Job
+    Create-Job-Subscription
+    Create-Printer-Subscription
+    Deactivate-Printer
+    Disable-Printer
+    Enable-Printer
+    Get-Job-Attributes
+    Get-Jobs
+    Get-Notifications
+    Get-Printer-Attributes
+    Get-Printer-Support-Files
+    Get-Printer-Supported-Values
+    Get-Subscription-Attributes
+    Get-Subscriptions
+    Hold-Job
+    Hold-New-Jobs
+    Pause-Printer
+    Pause-Printer-After-Current-Job
+    Print-Job
+    Print-URI
+    Promote-Job
+    Purge-Jobs
+    Release-Held-New-Jobs
+    Release-Job
+    Renew-Subscription
+    Reprocess-Job
+    Restart-Job
+    Restart-Printer
+    Resubmit-Job
+    Resume-Job
+    Resume-Printer
+    Schedule-Job-After
+    Send-Document
+    Send-Notifications
+    Send-URI
+    Set-Job-Attributes
+    Set-Printer-Attributes
+    Shutdown-Printer
+    Startup-Printer
+    Suspend-Current-Job
+    Validate-Job
+</pre>
+
+<h2 class="title"><a name="STATUS_CODES">Status Codes</a></h2>
+Status codes correspond to the hexadecimal numbers (0xHHHH) and names from RFC
+2911 and other IPP extension specifications. Here is a complete list:
+<pre>
+    client-error-attributes-not-settable
+    client-error-attributes-or-values-not-supported
+    client-error-bad-request
+    client-error-charset-not-supported
+    client-error-compression-error
+    client-error-compression-not-supported
+    client-error-conflicting-attributes
+    client-error-document-access-error
+    client-error-document-format-error
+    client-error-document-format-not-supported
+    client-error-forbidden
+    client-error-gone
+    client-error-ignored-all-notifications
+    client-error-ignored-all-subscriptions
+    client-error-not-authenticated
+    client-error-not-authorized
+    client-error-not-found
+    client-error-not-possible
+    client-error-print-support-file-not-found
+    client-error-request-entity-too-large
+    client-error-request-value-too-long
+    client-error-timeout
+    client-error-too-many-subscriptions
+    client-error-uri-scheme-not-supported
+    cups-see-other
+    redirection-other-site
+    server-error-busy
+    server-error-device-error
+    server-error-internal-error
+    server-error-job-canceled
+    server-error-multiple-document-jobs-not-supported
+    server-error-not-accepting-jobs
+    server-error-operation-not-supported
+    server-error-printer-is-deactivated
+    server-error-service-unavailable
+    server-error-temporary-error
+    server-error-version-not-supported
+    successful-ok
+    successful-ok-but-cancel-subscription
+    successful-ok-conflicting-attributes
+    successful-ok-events-complete
+    successful-ok-ignored-notifications
+    successful-ok-ignored-or-substituted-attributes
+    successful-ok-ignored-subscriptions
+    successful-ok-too-many-events
+</pre>
+
+<h2 class="title"><a name="TAGS">Tags</a></h2>
+Value and group tags correspond to the names from RFC 2911 and other IPP
+extension specifications. Here are the group tags:
+<pre>
+    event-notification-attributes-tag
+    job-attributes-tag
+    operation-attributes-tag
+    printer-attributes-tag
+    subscription-attributes-tag
+    unsupported-attributes-tag
+</pre>
+<p>Here are the value tags:
+<pre>
+    admin-define
+    boolean
+    charset
+    collection
+    dateTime
+    default
+    delete-attribute
+    enum
+    integer
+    keyword
+    mimeMediaType
+    nameWithLanguage
+    nameWithoutLanguage
+    naturalLanguage
+    no-value
+    not-settable
+    octetString
+    rangeOfInteger
+    resolution
+    textWithLanguage
+    textWithoutLanguage
+    unknown
+    unsupported
+    uri
+    uriScheme
+</pre>
+
+<h2 class="title"><a name="VARIABLES">Variables</a></h2>
+The <i>ipptool</i> program maintains a list of variables that can be used in any
+literal string or attribute value by specifying "$variable-name". Aside from
+variables defined using the "-d" option or "DEFINE" directive, the following
+pre-defined variables are available:
+<dl>
+<dt>$$
+</dt>
+<dd>Inserts a single "$" character.
+</dd>
+<dt>$ENV[name]
+</dt>
+<dd>Inserts the value of the named environment variable, or an empty string if the
+environment variable is not defined.
+</dd>
+<dt>$filename
+</dt>
+<dd>Inserts the filename provided to <i>ipptool</i> with the "-f" option.
+</dd>
+<dt>$hostname
+</dt>
+<dd>Inserts the hostname from the URI provided to <i>ipptool</i>.
+</dd>
+<dt>$job-id
+</dt>
+<dd>Inserts the last job-id value returned in a test response or 0 if no job-id has
+been seen.
+</dd>
+<dt>$job-uri
+</dt>
+<dd>Inserts the last job-uri value returned in a test response or an empty string if
+no job-uri has been seen.
+</dd>
+<dt>$scheme
+</dt>
+<dd>Inserts the scheme from the URI provided to <i>ipptool</i>.
+</dd>
+<dt>$notify-subscription-id
+</dt>
+<dd>Inserts the last notify-subscription-id value returnd in a test response or 0 if
+no notify-subscription-id has been seen.
+</dd>
+<dt>$port
+</dt>
+<dd>Inserts the port number from the URI provided to <i>ipptool</i>.
+</dd>
+<dt>$resource
+</dt>
+<dd>Inserts the resource path from the URI provided to <i>ipptool</i>.
+</dd>
+<dt>$uri
+</dt>
+<dd>Inserts the URI provided to <i>ipptool</i>.
+</dd>
+<dt>$user
+</dt>
+<dd>Inserts the current user's login name.
+</dd>
+<dt>$username
+</dt>
+<dd>Inserts the username from the URI provided to <i>ipptool</i>, if any.
+
+</dd>
+</dl>
+<h2 class="title"><a name="SEE_ALSO">See Also</a></h2>
+<a href='man-ipptool.html?TOPIC=Man+Pages'>ipptool(1)</a>,
+<br>
+<a href='http://localhost:631/help'>http://localhost:631/help</a>
+
+<h2 class="title"><a name="COPYRIGHT">Copyright</a></h2>
+Copyright 2007-2011 by Apple Inc.
+
+</body>
+</html>
index 6002729cfb98104da5a2c641387759f7bcd21977..36f694a3245b23bf3a261b6a65937d093951c2da 100644 (file)
@@ -335,229 +335,6 @@ quotas. This option has no effect if quotas are not enabled. The
 default setting is <CODE>No</CODE>.</P>
 
 
-<H2 CLASS="title"><A NAME="BrowseAddress">BrowseAddress</A></H2>
-
-<H3>Examples</H3>
-
-<PRE CLASS="command">
-BrowseAddress 255.255.255.255:631
-BrowseAddress 192.0.2.255:631
-BrowseAddress host.example.com:631
-BrowseAddress @LOCAL
-BrowseAddress @IF(name)
-</PRE>
-
-<H3>Description</H3>
-
-<P>The <CODE>BrowseAddress</CODE> directive specifies an address
-to send browsing information to. Multiple
-<CODE>BrowseAddress</CODE> directives can be specified to send
-browsing information to different networks or systems.</P>
-
-<P>The <CODE>@LOCAL</CODE> name will broadcast printer
-information to all local interfaces. The <CODE>@IF(name)</CODE>
-name will broadcast to the named interface.</P>
-
-<P>There is no default browse address.</P>
-
-<BLOCKQUOTE><B>Note:</B>
-
-<P>If you are using HP-UX 10.20 and a subnet that is not 24,
-16, or 8 bits, printer browsing (and in fact all broadcast
-reception) will not work. This problem appears to be fixed in
-HP-UX 11.0.</P>
-
-</BLOCKQUOTE>
-
-
-<H2 CLASS="title"><A NAME="BrowseAllow">BrowseAllow</A></H2>
-
-<H3>Examples</H3>
-
-<PRE CLASS="command">
-BrowseAllow from all
-BrowseAllow from none
-BrowseAllow from 192.0.2
-BrowseAllow from 192.0.2.0/24
-BrowseAllow from 192.0.2.0/255.255.255.0
-BrowseAllow from *.example.com
-BrowseAllow from @LOCAL
-BrowseAllow from @IF(name)
-</PRE>
-
-<H3>Description</H3>
-
-<P>The <CODE>BrowseAllow</CODE> directive specifies a system or
-network to accept browse packets from. The default is to accept
-browse packets from all hosts.</P>
-
-<P>Host and domain name matching require that you enable the <A
-HREF="#HostNameLookups"><CODE>HostNameLookups</CODE></A>
-directive.</P>
-
-<P>IP address matching supports exact matches, partial addresses that match
-networks using netmasks of 255.0.0.0, 255.255.0.0, and 255.255.255.0, or network
-addresses using the specified netmask or bit count. The <CODE>/mm</CODE>
-notation specifies a CIDR netmask, a shown in <A HREF="TABLE1">Table 1</A>.</P>
-
-<P>The <CODE>@LOCAL</CODE> name will allow browse data from all
-local interfaces. The <CODE>@IF(name)</CODE> name will allow
-browse data from the named interface. In both cases, CUPS only
-allows data from the network that the interface(s) are configured
-for - data arriving on the interface from a foreign network will
-<em>not</em> be allowed.</P>
-
-
-<H2 CLASS="title"><A NAME="BrowseDeny">BrowseDeny</A></H2>
-
-<H3>Examples</H3>
-
-<PRE CLASS="command">
-BrowseDeny from all
-BrowseDeny from none
-BrowseDeny from 192.0.2
-BrowseDeny from 192.0.2.0/24
-BrowseDeny from 192.0.2.0/255.255.255.0
-BrowseDeny from *.example.com
-BrowseDeny from @LOCAL
-BrowseDeny from @IF(name)
-</PRE>
-
-<H3>Description</H3>
-
-<P>The <CODE>BrowseDeny</CODE> directive specifies a system or
-network to reject browse packets from. The default is to not deny
-browse packets from any hosts.</P>
-
-<P>Host and domain name matching require that you enable the <A
-HREF="#HostNameLookups"><CODE>HostNameLookups</CODE></A>
-directive.</P>
-
-<P>IP address matching supports exact matches, partial addresses that match
-networks using netmasks of 255.0.0.0, 255.255.0.0, and 255.255.255.0, or network
-addresses using the specified netmask or bit count. The <CODE>/mm</CODE>
-notation specifies a CIDR netmask, a shown in <A HREF="TABLE1">Table 1</A>.</P>
-
-<P>The <CODE>@LOCAL</CODE> name will block browse data from all
-local interfaces. The <CODE>@IF(name)</CODE> name will block
-browse data from the named interface. In both cases, CUPS only
-blocks data from the network that the interface(s) are configured
-for - data arriving on the interface from a foreign network will
-<em>not</em> be blocked.</P>
-
-
-<H2 CLASS="title"><A NAME="BrowseInterval">BrowseInterval</A></H2>
-
-<H3>Examples</H3>
-
-<PRE CLASS="command">
-BrowseInterval 0
-BrowseInterval 30
-</PRE>
-
-<H3>Description</H3>
-
-<P>The <CODE>BrowseInterval</CODE> directive specifies the
-maximum amount of time between browsing updates. Specifying a
-value of 0 seconds disables outgoing browse updates but allows a
-server to receive printer information from other hosts.</P>
-
-<P>The <CODE>BrowseInterval</CODE> value should always be less
-than the <A HREF="#BrowseTimeout"><CODE>BrowseTimeout</CODE></A>
-value. Otherwise printers and classes will disappear from client
-systems between updates.</P>
-
-
-<H2 CLASS="title"><SPAN CLASS="info">CUPS 1.2/Mac OS X 10.5</SPAN><A NAME="BrowseLDAPBindDN">BrowseLDAPBindDN</A></H2>
-
-<H3>Examples</H3>
-
-<PRE CLASS="command">
-BrowseLDAPBindDN foo
-</PRE>
-
-<H3>Description</H3>
-
-<P>The <CODE>BrowseLDAPBindDN</CODE> directive specifies the LDAP
-domain name to use when listening for printer registrations. The
-default is undefined.</P>
-
-
-<H2 CLASS="title"><SPAN CLASS="info">CUPS 1.4/Mac OS X 10.6</SPAN><A NAME="BrowseLDAPCACertFile">BrowseLDAPCACertFile</A></H2>
-
-<H3>Examples</H3>
-
-<PRE CLASS="command">
-BrowseLDAPCACertFile /etc/cups/ssl/certs
-</PRE>
-
-<H3>Description</H3>
-
-<P>The <CODE>BrowseLDAPCACertFile</CODE> directive specifies the SSL certificate
-authority file to use for LDAP + SSL. The default is undefined.</P>
-
-
-<H2 CLASS="title"><SPAN CLASS="info">CUPS 1.2/Mac OS X 10.5</SPAN><A NAME="BrowseLDAPDN">BrowseLDAPDN</A></H2>
-
-<H3>Examples</H3>
-
-<PRE CLASS="command">
-BrowseLDAPDN bar
-</PRE>
-
-<H3>Description</H3>
-
-<P>The <CODE>BrowseLDAPDN</CODE> directive specifies the LDAP
-domain name to use when registering local shared printers. The
-default is undefined.</P>
-
-
-<H2 CLASS="title"><SPAN CLASS="info">CUPS 1.2/Mac OS X 10.5</SPAN><A NAME="BrowseLDAPPassword">BrowseLDAPPassword</A></H2>
-
-<H3>Examples</H3>
-
-<PRE CLASS="command">
-BrowseLDAPPassword foo123
-</PRE>
-
-<H3>Description</H3>
-
-<P>The <CODE>BrowseLDAPPassword</CODE> directive specifies the
-access password to use when connecting to the LDAP server. The
-default is undefined.</P>
-
-
-<H2 CLASS="title"><SPAN CLASS="info">CUPS 1.2/Mac OS X 10.5</SPAN><A NAME="BrowseLDAPServer">BrowseLDAPServer</A></H2>
-
-<H3>Examples</H3>
-
-<PRE CLASS="command">
-BrowseLDAPServer localhost
-</PRE>
-
-<H3>Description</H3>
-
-<P>The <CODE>BrowseLDAPServer</CODE> directive specifies the name
-of the LDAP server to connect to. The default is undefined.</P>
-
-
-<H2 CLASS="title"><A NAME="BrowseLocalOptions">BrowseLocalOptions</A></H2>
-
-<H3>Examples</H3>
-
-<PRE CLASS="command">
-BrowseLocalOptions compression=yes
-BrowseLocalOptions encryption=required
-BrowseLocalOptions compression=yes&amp;encryption=required
-</PRE>
-
-<H3>Description</H3>
-
-<P>The <CODE>BrowseLocalOptions</CODE> directive specifies
-additional IPP backend options to advertise with local shared
-printers. The default is to not include any options.</P>
-
-
 <H2 CLASS="title"><SPAN CLASS="info">CUPS 1.2/Mac OS X 10.5</SPAN><A NAME="BrowseLocalProtocols">BrowseLocalProtocols</A></H2>
 
 <H3>Examples</H3>
@@ -565,13 +342,7 @@ printers. The default is to not include any options.</P>
 <PRE CLASS="command">
 BrowseLocalProtocols all
 BrowseLocalProtocols none
-BrowseLocalProtocols cups
 BrowseLocalProtocols dnssd
-BrowseLocalProtocols ldap
-BrowseLocalProtocols lpd
-BrowseLocalProtocols slp
-BrowseLocalProtocols smb
-BrowseLocalProtocols cups dnssd
 </PRE>
 
 <H3>Description</H3>
@@ -582,230 +353,6 @@ network. Multiple protocols can be specified by separating them
 with spaces. The default is "<CODE>@CUPS_BROWSE_LOCAL_PROTOCOLS@</CODE>".</P>
 
 
-<H2 CLASS="title"><A NAME="BrowseOrder">BrowseOrder</A></H2>
-
-<H3>Examples</H3>
-
-<PRE CLASS="command">
-BrowseOrder allow,deny
-BrowseOrder deny,allow
-</PRE>
-
-<H3>Description</H3>
-
-<P>The <CODE>BrowseOrder</CODE> directive specifies the order of
-allow/deny processing. The default order is
-<CODE>deny,allow</CODE>:</P>
-
-<UL>
-
-       <LI><CODE>allow,deny</CODE> - Deny browse packets by
-       default, then check <CODE>BrowseAllow</CODE> lines
-       followed by <CODE>BrowseDeny</CODE> lines.</LI>
-
-       <LI><CODE>deny,allow</CODE> - Allow browse packets by
-       default, then check <CODE>BrowseDeny</CODE> lines
-       followed by <CODE>BrowseAllow</CODE> lines.</LI>
-
-</UL>
-
-
-<H2 CLASS="title"><A NAME="BrowsePoll">BrowsePoll</A></H2>
-
-<H3>Examples</H3>
-
-<PRE CLASS="command">
-BrowsePoll 192.0.2.2:631
-BrowsePoll host.example.com:631
-</PRE>
-
-<H3>Description</H3>
-
-<P>The <CODE>BrowsePoll</CODE> directive polls a server for
-available printers once every <A
-HREF="#BrowseInterval"><CODE>BrowseInterval</CODE></A> seconds.
-Multiple <CODE>BrowsePoll</CODE> directives can be specified to
-poll multiple servers.</P>
-
-<P>If <CODE>BrowseInterval</CODE> is set to 0 then the server is
-polled once every 30 seconds.</P>
-
-
-<H2 CLASS="title"><A NAME="BrowsePort">BrowsePort</A></H2>
-
-<H3>Examples</H3>
-
-<PRE CLASS="command">
-BrowsePort 631
-BrowsePort 9999
-</PRE>
-
-<H3>Description</H3>
-
-<P>The <CODE>BrowsePort</CODE> directive specifies the UDP port number
-used for browse packets. The default port number is 631.</P>
-
-<BLOCKQUOTE><B>Note:</B>
-
-<P>You must set the <CODE>BrowsePort</CODE> to the same value
-on all of the systems that you want to see.
-
-</BLOCKQUOTE>
-
-
-<H2 CLASS="title"><SPAN CLASS="info">CUPS 1.1.10</SPAN><A NAME="BrowseProtocols">BrowseProtocols</A></H2>
-
-<H3>Examples</H3>
-
-<PRE CLASS="command">
-BrowseProtocols all
-BrowseProtocols none
-BrowseProtocols cups
-BrowseProtocols dnssd
-BrowseProtocols ldap
-BrowseProtocols lpd
-BrowseProtocols slp
-BrowseProtocols smb
-BrowseProtocols cups dnssd
-</PRE>
-
-<H3>Description</H3>
-
-<P>The <CODE>BrowseProtocols</CODE> directive specifies the
-protocols to use when showing and advertising shared printers on
-the local network. Multiple protocols can be specified by
-separating them with spaces. The default protocol is
-"<CODE>@CUPS_BROWSE_LOCAL_PROTOCOLS@</CODE>" for
-<A HREF="#BrowseLocalProtocols"><CODE>BrowseLocalProtocols</CODE></A> and
-"<CODE>@CUPS_BROWSE_REMOTE_PROTOCOLS@</CODE>" for
-<A HREF="#BrowseRemoteProtocols"><CODE>BrowseRemoteProtocols</CODE></A>.</P>
-
-<BLOCKQUOTE><B>Note:</B>
-
-<P>When using the <CODE>SLP</CODE> protocol, you must have at least
-one Directory Agent (DA) server on your network. Otherwise the
-CUPS scheduler (<CODE>cupsd</CODE>) will not respond to client
-requests for several seconds while polling the network.</P>
-
-</BLOCKQUOTE>
-
-
-<H2 CLASS="title"><A NAME="BrowseRelay">BrowseRelay</A></H2>
-
-<H3>Examples</H3>
-
-<PRE CLASS="command">
-BrowseRelay 193.0.2.1 192.0.2.255
-BrowseRelay 193.0.2.0/255.255.255.0 192.0.2.255
-BrowseRelay 193.0.2.0/24 192.0.2.255
-BrowseRelay *.example.com 192.0.2.255
-BrowseRelay host.example.com 192.0.2.255
-</PRE>
-
-<H3>Description</H3>
-
-<P>The <CODE>BrowseRelay</CODE> directive specifies source and
-destination addresses for relaying browsing information from one
-host or network to another. Multiple <CODE>BrowseRelay</CODE>
-directives can be specified as needed.</P>
-
-<P><CODE>BrowseRelay</CODE> is typically used on systems that
-bridge multiple subnets using one or more network interfaces. It
-can also be used to relay printer information from polled servers
-with the line:</P>
-
-<PRE CLASS="command">
-BrowseRelay 127.0.0.1 192.0.2.255
-</PRE>
-
-<P>This effectively provides access to printers on a WAN for all
-clients on the LAN. Use multiple <CODE>BrowseRelay</CODE> lines to
-relay information to multiple subnets.</P>
-
-
-<H2 CLASS="title"><A NAME="BrowseRemoteOptions">BrowseRemoteOptions</A></H2>
-
-<H3>Examples</H3>
-
-<PRE CLASS="command">
-BrowseRemoteOptions compression=yes
-BrowseRemoteOptions encryption=required
-BrowseRemoteOptions ?compression=yes&amp;encryption=required
-</PRE>
-
-<H3>Description</H3>
-
-<P>The <CODE>BrowseRemoteOptions</CODE> directive specifies
-additional IPP backend options to include with remote shared
-printers. If the options string begins with a question mark (?),
-the options replace any options specified by the remote server.
-The default is to not include any options.</P>
-
-
-<H2 CLASS="title"><SPAN CLASS="info">CUPS 1.2/Mac OS X 10.5</SPAN><A NAME="BrowseRemoteProtocols">BrowseRemoteProtocols</A></H2>
-
-<H3>Examples</H3>
-
-<PRE CLASS="command">
-BrowseRemoteProtocols all
-BrowseRemoteProtocols none
-BrowseRemoteProtocols cups
-BrowseRemoteProtocols ldap
-BrowseRemoteProtocols slp
-</PRE>
-
-<H3>Description</H3>
-
-<P>The <CODE>BrowseRemoteProtocols</CODE> directive specifies the
-protocols to use when finding remote shared printers on the
-network. Multiple protocols can be specified by separating them
-with spaces. The default is "<CODE>@CUPS_BROWSE_REMOTE_PROTOCOLS@</CODE>".</P>
-
-
-<H2 CLASS="title"><A NAME="BrowseShortNames">BrowseShortNames</A></H2>
-
-<H3>Examples</H3>
-
-<PRE CLASS="command">
-BrowseShortNames Yes
-BrowseShortNames No
-</PRE>
-
-<H3>Description</H3>
-
-<P>The <CODE>BrowseShortNames</CODE> directive specifies whether
-or not short names are used for remote printers when possible.
-Short names are just the remote printer name, without the server
-("printer"). If more than one remote printer is detected with the
-same name, the printers will have long names ("printer@server1",
-"printer@server2".)</P>
-
-<P>The default value for this option is <CODE>@CUPS_BROWSE_SHORT_NAMES@</CODE>.</P>
-
-
-<H2 CLASS="title"><A NAME="BrowseTimeout">BrowseTimeout</A></H2>
-
-<H3>Examples</H3>
-
-<PRE CLASS="command">
-BrowseTimeout 300
-BrowseTimeout 60
-</PRE>
-
-<H3>Description</H3>
-
-<P>The <CODE>BrowseTimeout</CODE> directive sets the timeout for
-printer or class information that is received in browse packets.
-Once a printer or class times out it is removed from the list of
-available destinations.</P>
-
-<P>The <CODE>BrowseTimeout</CODE> value should always be greater
-than the <A
-HREF="#BrowseInterval"><CODE>BrowseInterval</CODE></A> value.
-Otherwise printers and classes will disappear from client systems
-between updates.</P>
-
-
 <H2 CLASS="title"><A NAME="BrowseWebIF">BrowseWebIF</A></H2>
 
 <H3>Examples</H3>
@@ -834,24 +381,9 @@ Browsing Off
 <H3>Description</H3>
 
 <P>The <CODE>Browsing</CODE> directive controls whether or not
-network printer browsing is enabled. The default setting is
+printer sharing is enabled. The default setting is
 <CODE>@CUPS_BROWSING@</CODE>.</P>
 
-<P>This directive does not enable sharing of local printers by
-itself; you must also use the <A
-HREF="#BrowseAddress"><CODE>BrowseAddress</CODE></A> or <A
-HREF="#BrowseProtocols"><CODE>BrowseProtocols</CODE></A>
-directives to advertise local printers to other systems.</P>
-
-<BLOCKQUOTE><B>Note:</B>
-
-<P>If you are using HP-UX 10.20 and a subnet that is not 24,
-16, or 8 bits, printer browsing (and in fact all broadcast
-reception) will not work. This problem appears to be fixed in
-HP-UX 11.0.</P>
-
-</BLOCKQUOTE>
-
 
 <H2 CLASS="title"><SPAN CLASS="info">CUPS 1.1.7</SPAN><A NAME="Classification">Classification</A></H2>
 
@@ -1382,25 +914,6 @@ system-specific but is usually <CODE>lp</CODE> or
 <CODE>nobody</CODE>.</P>
 
 
-<H2 CLASS="title"><SPAN CLASS="info">CUPS 1.1.10</SPAN><A NAME="HideImplicitMembers">HideImplicitMembers</A></H2>
-
-<H3>Examples</H3>
-
-<PRE CLASS="command">
-HideImplicitMembers Yes
-HideImplicitMembers No
-</PRE>
-
-<H3>Description</H3>
-
-<P>The <CODE>HideImplicitMembers</CODE> directive controls
-whether the individual printers in an implicit class are hidden
-from the user. The default is <CODE>Yes</CODE>.</P>
-
-<P><A HREF="#ImplicitClasses"><CODE>ImplicitClasses</CODE></A>
-must be enabled for this directive to have any effect.</P>
-
-
 <H2 CLASS="title"><A NAME="HostNameLookups">HostNameLookups</A></H2>
 
 <H3>Examples</H3>
@@ -1427,45 +940,6 @@ performance problems with hostname lookups. Set this option to
 required.</P>
 
 
-<H2 CLASS="title"><SPAN CLASS="info">CUPS 1.1.10</SPAN><A NAME="ImplicitAnyClasses">ImplicitAnyClasses</A></H2>
-
-<H3>Examples</H3>
-
-<PRE CLASS="command">
-ImplicitAnyClasses On
-ImplicitAnyClasses Off
-</PRE>
-
-<H3>Description</H3>
-
-<P>The <CODE>ImplicitAnyClasses</CODE> directive controls
-whether implicit classes for local and remote printers are
-created with the name <CODE>AnyPrinter</CODE>. The default
-setting is <CODE>Off</CODE>.</P>
-
-<P><A HREF="#ImplicitClasses"><CODE>ImplicitClasses</CODE></A>
-must be enabled for this directive to have any effect.</P>
-
-
-<H2 CLASS="title"><A NAME="ImplicitClasses">ImplicitClasses</A></H2>
-
-<H3>Examples</H3>
-
-<PRE CLASS="command">
-ImplicitClasses On
-ImplicitClasses Off
-</PRE>
-
-<H3>Description</H3>
-
-<P>The <CODE>ImplicitClasses</CODE> directive controls whether
-implicit classes are created based upon the available network
-printers and classes. The default setting is
-<CODE>@CUPS_IMPLICIT_CLASSES@</CODE> but is automatically turned
-<CODE>Off</CODE> if <A HREF="#Browsing"><CODE>Browsing</CODE></A> is turned
-<CODE>Off</CODE>.</P>
-
-
 <H2 CLASS="title"><SPAN CLASS="info">CUPS 1.1.9</SPAN><A NAME="Include">Include</A></H2>
 
 <H3>Examples</H3>
index 076cc4b9c69e7ba608514d64eeb7ed4edc8bc442..46453eb2e91b1b50c09c92e15d55852d07cbaa8d 100644 (file)
@@ -23,7 +23,7 @@ DeskJet root 2 [20/May/1999:19:21:05 +0000] 2 1 acme-123 localhost myjob letter
 
 </P>
 
-<p>The <a href="ref-cupsd_conf.html#PageLogFormat"><code>PageLogFormat</code></a>
+<p>The <a href="ref-cupsd-conf.html#PageLogFormat"><code>PageLogFormat</code></a>
 directive can be used to change this information.</p>
 
 <P>The <I>printer</I> field contains the name of the printer that
index eed4432d863c3e0c168f6d35e849b7a51e54c1aa..0c03edf6838d893195ea8656deb859b224cf72fd 100644 (file)
@@ -1387,7 +1387,7 @@ setpagedevice(
   * Found the start of the dictionary, empty the stack to this point...
   */
 
-  st->num_objs = obj - st->objs;
+  st->num_objs = (int)(obj - st->objs);
 
  /*
   * Now pull /name and value pairs from the dictionary...
index bb5725206b2c0e63503ea808788221f639ed765e..dd3ef5a30eba194efe328488d89763b45911b6ef 100644 (file)
@@ -504,7 +504,7 @@ cupsRasterReadPixels(cups_raster_t *r,      /* I - Raster stream */
       * Copy fragment from buffer...
       */
 
-      if ((unsigned)(bytes = r->pend - r->pcurrent) > remaining)
+      if ((unsigned)(bytes = (int)(r->pend - r->pcurrent)) > remaining)
         bytes = remaining;
 
       memcpy(p, r->pcurrent, bytes);
@@ -830,8 +830,8 @@ cupsRasterWritePixels(cups_raster_t *r,     /* I - Raster stream */
     * Figure out the number of remaining bytes on the current line...
     */
 
-    if ((bytes = remaining) > (r->pend - r->pcurrent))
-      bytes = r->pend - r->pcurrent;
+    if ((bytes = remaining) > (int)(r->pend - r->pcurrent))
+      bytes = (int)(r->pend - r->pcurrent);
 
     if (r->count > 0)
     {
@@ -1047,8 +1047,10 @@ cups_raster_read(cups_raster_t *r,       /* I - Raster stream */
 
   if ((size_t)count > r->bufsize)
   {
-    int offset = r->bufptr - r->buffer;        /* Offset to current start of buffer */
-    int end = r->bufend - r->buffer;   /* Offset to current end of buffer */
+    int offset = (int)(r->bufptr - r->buffer);
+                                       /* Offset to current start of buffer */
+    int end = (int)(r->bufend - r->buffer);
+                                       /* Offset to current end of buffer */
     unsigned char *rptr;               /* Pointer in read buffer */
 
     if (r->buffer)
@@ -1069,7 +1071,7 @@ cups_raster_read(cups_raster_t *r,        /* I - Raster stream */
   * Loop until we have read everything...
   */
 
-  for (total = 0, remaining = r->bufend - r->bufptr;
+  for (total = 0, remaining = (int)(r->bufend - r->bufptr);
        total < bytes;
        total += count, buf += count)
   {
@@ -1387,7 +1389,7 @@ cups_raster_write(
     }
   }
 
-  return (cups_raster_io(r, r->buffer, wptr - r->buffer));
+  return (cups_raster_io(r, r->buffer, (int)(wptr - r->buffer)));
 }
 
 
@@ -1405,7 +1407,11 @@ cups_read_fd(void          *ctx, /* I - File descriptor as pointer */
   ssize_t      count;                  /* Number of bytes read */
 
 
+#ifdef WIN32 /* Sigh */
+  while ((count = read(fd, buf, (unsigned)bytes)) < 0)
+#else
   while ((count = read(fd, buf, bytes)) < 0)
+#endif /* WIN32 */
     if (errno != EINTR && errno != EAGAIN)
       return (-1);
 
@@ -1453,7 +1459,11 @@ cups_write_fd(void          *ctx,        /* I - File descriptor pointer */
   ssize_t      count;                  /* Number of bytes written */
 
 
+#ifdef WIN32 /* Sigh */
+  while ((count = write(fd, buf, (unsigned)bytes)) < 0)
+#else
   while ((count = write(fd, buf, bytes)) < 0)
+#endif /* WIN32 */
     if (errno != EINTR && errno != EAGAIN)
       return (-1);
 
index c941c02db78263abdb6f72b601db42af865b8f6e..aec9905d1e35ac881bbd3af2e40652da34b1bd25 100644 (file)
@@ -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 "CUPS" "18 May 2011" "Apple Inc."
+.TH cupsd.conf 5 "CUPS" "3 November 2011" "Apple Inc."
 .SH NAME
 cupsd.conf \- server configuration file for cups
 .SH DESCRIPTION
@@ -94,121 +94,9 @@ AutoPurgeJobs No
 Specifies whether to purge job history data automatically when
 it is no longer required for quotas.
 .TP 5
-BrowseAddress ip-address
-.TP 5
-BrowseAddress @IF(name)
-.TP 5
-BrowseAddress @LOCAL
-.br
-Specifies a broadcast address for outgoing printer information packets.
-.TP 5
-BrowseAllow all
-.TP 5
-BrowseAllow none
-.TP 5
-BrowseAllow host.domain.com
-.TP 5
-BrowseAllow *.domain.com
-.TP 5
-BrowseAllow ip-address
-.TP 5
-BrowseAllow ip-address/netmask
-.TP 5
-BrowseAllow ip-address/mm
-.TP 5
-BrowseAllow @IF(name)
-.TP 5
-BrowseAllow @LOCAL
-.br
-Allows incoming printer information packets from the named host or address.
-.TP 5
-BrowseDeny all
-.TP 5
-BrowseDeny none
-.TP 5
-BrowseDeny host.domain.com
-.TP 5
-BrowseDeny *.domain.com
-.TP 5
-BrowseDeny ip-address
-.TP 5
-BrowseDeny ip-address/netmask
-.TP 5
-BrowseDeny ip-address/mm
-.TP 5
-BrowseDeny @IF(name)
-.TP 5
-BrowseDeny @LOCAL
-.br
-Denies incoming printer information packets from the named host or address.
-.TP 5
-BrowseInterval seconds
-.br
-Specifies the maximum interval between printer information broadcasts.
-.TP 5
-BrowseLDAPBindDN
-.br
-Specifies the LDAP domain name to use when registering printers.
-.TP 5
-BrowseLDAPCACertFile
-.br
-Specifies the SSL certificate authority file to use.
-.TP 5
-BrowseLDAPDN
-.br
-Specifies the LDAP domain name to use when discovering printers.
-.TP 5
-BrowseLDAPPassword
+BrowseLocalProtocols [All] [DNSSD]
 .br
-Specifies the password to use when accessing the LDAP server.
-.TP 5
-BrowseLDAPServer
-.br
-Specifies the LDAP server to use.
-.TP 5
-BrowseOrder allow,deny
-.TP 5
-BrowseOrder deny,allow
-.br
-Specifies the order of printer information access control (allow,deny or deny,allow)
-.TP 5
-BrowsePoll host-or-ip-address
-.br
-Specifies a server to poll for printer information.
-.TP 5
-BrowsePort port
-.br
-Specifies the port to listen to for printer information packets.
-.TP 5
-BrowseProtocols [All] [CUPS] [DNSSD] [LDAP] [SLP]
-.br
-Specifies the protocols to use for printer browsing.
-.TP 5
-BrowseLocalProtocols [All] [CUPS] [DNSSD] [LDAP] [SLP]
-.br
-Specifies the protocols to use for local printer browsing.
-.TP 5
-BrowseRemoteProtocols [All] [CUPS] [DNSSD] [LDAP] [SLP]
-.br
-Specifies the protocols to use for remote printer browsing.
-.TP 5
-BrowseRelay from-address to-address
-.br
-Specifies that printer information packets should be relayed from one host or
-network to another.
-.TP 5
-BrowseShortNames Yes
-.TP 5
-BrowseShortNames No
-.br
-Specifies whether remote printers will use short names ("printer") or not
-("printer@server"). This option is ignored if more than one remote printer
-exists with the same name.
-.TP 5
-BrowseTimeout seconds
-.br
-Specifies the maximum interval between printer information updates before
-remote printers will be removed from the list of available printers.
+Specifies the protocols to use for local printer sharing.
 .TP 5
 BrowseWebIF Yes
 .TP 5
@@ -362,12 +250,6 @@ Group group-name-or-number
 Specifies the group name or ID that will be used when executing
 external programs.
 .TP 5
-HideImplicitMembers Yes
-.TP 5
-HideImplicitMembers No
-.br
-Specifies whether to hide members of implicit classes.
-.TP 5
 HostNameLookups On
 .TP 5
 HostNameLookups Off
@@ -376,21 +258,6 @@ HostNameLookups Double
 .br
 Specifies whether or not to do reverse lookups on client addresses.
 .TP 5
-ImplicitAnyClasses Yes
-.TP 5
-ImplicitAnyClasses No
-.br
-Specifies whether or not to create implicit classes for local and
-remote printers, e.g. "AnyPrinter" from "Printer", "Printer@server1",
-and "Printer@server2".
-.TP 5
-ImplicitClasses Yes
-.TP 5
-ImplicitClasses No
-.br
-Specifies whether or not to create implicit classes from identical
-remote printers.
-.TP 5
 Include filename
 .br
 Includes the named file.
index 7ee15519d54340a6208535e2936904c0b81ab96f..da2db951dab776541ce8f3151d729c10f1e23d30 100644 (file)
@@ -632,7 +632,7 @@ print_attributes(ipp_t *ipp,                /* I - IPP request */
       fprintf(stderr, "DEBUG: %*s%s:\n\n", indent - 4, "", ippTagString(group));
     }
 
-    _ippAttrString(attr, buffer, sizeof(buffer));
+    ippAttributeString(attr, buffer, sizeof(buffer));
 
     fprintf(stderr, "DEBUG: %*s%s (%s%s) %s", indent, "", attr->name,
             attr->num_values > 1 ? "1setOf " : "",
index 9c9aa75538447c219c2f4c337492f033bd903738..f42c921a2cc293d5187296e6cec953614f2643ab 100644 (file)
@@ -3,7 +3,7 @@
  *
  *   RSS notifier for CUPS.
  *
- *   Copyright 2007-2010 by Apple Inc.
+ *   Copyright 2007-2011 by Apple Inc.
  *   Copyright 2007 by Easy Software Products.
  *
  *   These coded instructions, statements, and computer programs are the
@@ -33,6 +33,7 @@
 #include <cups/string-private.h>
 #include <cups/array.h>
 #include <sys/select.h>
+#include <cups/ipp-private.h>  /* TODO: Update so we don't need this */
 
 
 /*
index 7e91f18cbbe2e576ea6f3f0b92ef25f210daf629..faa846d083068364dac801ba24d17a1461fc1180 100644 (file)
@@ -113,7 +113,7 @@ print_attributes(ipp_t *ipp,                /* I - IPP request */
       fprintf(stderr, "DEBUG: %*s%s:\n\n", indent - 4, "", ippTagString(group));
     }
 
-    _ippAttrString(attr, buffer, sizeof(buffer));
+    ippAttributeString(attr, buffer, sizeof(buffer));
 
     fprintf(stderr, "DEBUG: %*s%s (%s%s) %s", indent, "", attr->name,
             attr->num_values > 1 ? "1setOf " : "",
index d562437a32092ba9baa9121586b210d30ae80ff2..c8570be6277eaa05db9e3fd4d04bff2e27d56226 100644 (file)
@@ -51,8 +51,6 @@ COBJS =       \
                cups-deviced.o \
                cups-exec.o \
                cups-lpd.o \
-               cups-polld.o \
-               testdirsvc.o \
                testlpd.o \
                testmime.o \
                testspeed.o \
@@ -68,7 +66,6 @@ LIBTARGETS =  \
                libcupsmime.a
 
 UNITTARGETS =  \
-               testdirsvc \
                testlpd \
                testmime \
                testspeed \
@@ -80,8 +77,7 @@ PROGRAMS =    \
                cups-deviced \
                cups-driverd \
                cups-exec \
-               cups-lpd \
-               cups-polld
+               cups-lpd
 
 TARGETS        =       \
                $(LIBTARGETS) \
@@ -215,10 +211,6 @@ install-exec:
        $(INSTALL_DIR) -m 755 $(SBINDIR)
        $(INSTALL_BIN) -m 500 cupsd $(SBINDIR)
        $(INSTALL_BIN) cupsfilter $(SBINDIR)
-       -if test "x`uname`" = xDarwin; then \
-               $(INSTALL_DIR) $(BUILDROOT)/System/Library/Printers/Libraries; \
-               $(LN) $(sbindir)/cupsfilter $(BUILDROOT)/System/Library/Printers/Libraries/convert; \
-       fi
        echo Installing programs in $(SERVERBIN)/daemon...
        $(INSTALL_DIR) -m 755 $(SERVERBIN)
        $(INSTALL_DIR) -m 755 $(SERVERBIN)/daemon
@@ -438,15 +430,6 @@ cups-lpd:  cups-lpd.o ../cups/$(LIBCUPS)
        $(CC) $(LDFLAGS) -o cups-lpd cups-lpd.o $(LIBS)
 
 
-#
-# Make the polling daemon, "cups-polld".
-#
-
-cups-polld:    cups-polld.o ../cups/$(LIBCUPS)
-       echo Linking $@...
-       $(CC) $(LDFLAGS) -o cups-polld cups-polld.o $(LIBS)
-
-
 #
 # libcupsmime.so.1, libcupsmime.sl.1
 #
@@ -506,15 +489,6 @@ libcupsmime.a:     $(LIBOBJS)
        $(RANLIB) $@
 
 
-#
-# Make the test program, "testdirsvc".
-#
-
-testdirsvc:    testdirsvc.o
-       echo Linking $@...
-       $(CC) $(LDFLAGS) -o testdirsvc testdirsvc.o $(COMMONLIBS) $(NETLIBS)
-
-
 #
 # Make the test program, "testlpd".
 #
index 7de29e707eca3f910a24c5ebcf9ca88b80c3547e..f1ae1c3854411969a7b53100e2fef00029f08bf0 100644 (file)
@@ -206,7 +206,7 @@ cupsdAddCert(int        pid,                /* I - Process ID */
          *textptr = ',';
 
        cupsdLogMessage(CUPSD_LOG_ERROR, "ACL: %s", text);
-       free(text);
+       acl_free(text);
       }
 #  endif /* HAVE_MBR_UID_TO_UUID */
 
index e1da0aa6a3c432929e366a42276dee28a046f7d0..f5b5bcc620b53dcd82e0272a7c5022b4a79d4861 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * "$Id: classes.c 7724 2008-07-14 06:06:06Z mike $"
+ * "$Id: classes.c 10104 2011-11-04 06:37:03Z mike $"
  *
  *   Printer class routines for the CUPS scheduler.
  *
@@ -22,8 +22,6 @@
  *   cupsdFindClass()                - Find the named class.
  *   cupsdLoadAllClasses()           - Load classes from the classes.conf file.
  *   cupsdSaveAllClasses()           - Save classes to the classes.conf file.
- *   cupsdUpdateImplicitClasses()    - Update the accepting state of implicit
- *                                     classes.
  */
 
 /*
@@ -184,24 +182,9 @@ cupsdDeletePrinterFromClasses(
   for (c = (cupsd_printer_t *)cupsArrayFirst(Printers);
        c;
        c = (cupsd_printer_t *)cupsArrayNext(Printers))
-    if (c->type & (CUPS_PRINTER_CLASS | CUPS_PRINTER_IMPLICIT))
+    if (c->type & CUPS_PRINTER_CLASS)
       changed |= cupsdDeletePrinterFromClass(c, p);
 
- /*
-  * Then clean out any empty implicit classes...
-  */
-
-  for (c = (cupsd_printer_t *)cupsArrayFirst(ImplicitPrinters);
-       c;
-       c = (cupsd_printer_t *)cupsArrayNext(ImplicitPrinters))
-    if (c->num_printers == 0)
-    {
-      cupsdLogMessage(CUPSD_LOG_DEBUG, "Deleting implicit class \"%s\"...",
-                      c->name);
-      cupsdDeletePrinter(c, 0);
-      changed = 1;
-    }
-
   return (changed);
 }
 
@@ -279,8 +262,7 @@ cupsdFindClass(const char *name)    /* I - Name of class */
   cupsd_printer_t      *c;             /* Current class/printer */
 
 
-  if ((c = cupsdFindDest(name)) != NULL &&
-      (c->type & (CUPS_PRINTER_CLASS | CUPS_PRINTER_IMPLICIT)))
+  if ((c = cupsdFindDest(name)) != NULL && (c->type & CUPS_PRINTER_CLASS))
     return (c);
   else
     return (NULL);
@@ -443,9 +425,8 @@ cupsdLoadAllClasses(void)
        {
          cupsdSetString(&temp->make_model, "Remote Printer on unknown");
 
-          temp->state       = IPP_PRINTER_STOPPED;
-         temp->type        |= CUPS_PRINTER_REMOTE;
-         temp->browse_time = 2147483647;
+          temp->state = IPP_PRINTER_STOPPED;
+         temp->type  |= CUPS_PRINTER_REMOTE;
 
          cupsdSetString(&temp->location, "Location Unknown");
          cupsdSetString(&temp->info, "No Information Available");
@@ -733,7 +714,6 @@ cupsdSaveAllClasses(void)
     */
 
     if ((pclass->type & CUPS_PRINTER_REMOTE) ||
-        (pclass->type & CUPS_PRINTER_IMPLICIT) ||
         !(pclass->type & CUPS_PRINTER_CLASS))
       continue;
 
@@ -834,35 +814,5 @@ cupsdSaveAllClasses(void)
 
 
 /*
- * 'cupsdUpdateImplicitClasses()' - Update the accepting state of implicit
- *                                  classes.
- */
-
-void
-cupsdUpdateImplicitClasses(void)
-{
-  int                  i;              /* Looping var */
-  cupsd_printer_t      *pclass;        /* Current class */
-  int                  accepting;      /* printer-is-accepting-jobs value */
-
-
-  for (pclass = (cupsd_printer_t *)cupsArrayFirst(ImplicitPrinters);
-       pclass;
-       pclass = (cupsd_printer_t *)cupsArrayNext(ImplicitPrinters))
-  {
-   /*
-    * Loop through the printers to come up with a composite state...
-    */
-
-    for (i = 0, accepting = 0; i < pclass->num_printers; i ++)
-      if ((accepting = pclass->printers[i]->accepting) != 0)
-       break;
-
-    pclass->accepting = accepting;
-  }
-}
-
-
-/*
- * End of "$Id: classes.c 7724 2008-07-14 06:06:06Z mike $".
+ * End of "$Id: classes.c 10104 2011-11-04 06:37:03Z mike $".
  */
index ef415762ab42d37fa20e90f3401bf005df9b6da8..0170b97e7dfaf8a004c89c7da443eb981877fc90 100644 (file)
@@ -3,7 +3,7 @@
  *
  *   Printer class definitions for the CUPS scheduler.
  *
- *   Copyright 2007-2010 by Apple Inc.
+ *   Copyright 2007-2011 by Apple Inc.
  *   Copyright 1997-2005 by Easy Software Products, all rights reserved.
  *
  *   These coded instructions, statements, and computer programs are the
@@ -28,7 +28,6 @@ extern cupsd_printer_t        *cupsdFindAvailablePrinter(const char *name);
 extern cupsd_printer_t *cupsdFindClass(const char *name);
 extern void            cupsdLoadAllClasses(void);
 extern void            cupsdSaveAllClasses(void);
-extern void            cupsdUpdateImplicitClasses(void);
 
 
 /*
index c8995916a539a6a7df52d79b040823776e6f8457..2ffdb56c7a9d1cee7867425d3c7e50e8ee61b416 100644 (file)
@@ -2842,7 +2842,7 @@ cupsdWriteClient(cupsd_client_t *con)     /* I - Client connection */
     bytes     = ipp_state != IPP_ERROR &&
                 (con->file >= 0 || ipp_state != IPP_DATA);
   }
-  else if ((bytes = read(con->file, con->header,
+  else if ((bytes = read(con->file, con->header + con->header_used,
                         sizeof(con->header) - con->header_used)) > 0)
   {
     con->header_used += bytes;
index 2d30822b9531f71d9d248fb2f1902ce81559ac93..85dce903501df772844a9fd654fd3205b9e975f6 100644 (file)
@@ -71,7 +71,7 @@ typedef enum
 
 typedef struct
 {
-  char                 *name;          /* Name of variable */
+  const char           *name;          /* Name of variable */
   void                 *ptr;           /* Pointer to variable */
   cupsd_vartype_t      type;           /* Type (int, string, address) */
 } cupsd_var_t;
@@ -88,21 +88,6 @@ static const cupsd_var_t     variables[] =
 #ifdef HAVE_DNSSD
   { "BrowseDNSSDRegType",      &DNSSDRegType,          CUPSD_VARTYPE_STRING },
 #endif /* HAVE_DNSSD */
-  { "BrowseInterval",          &BrowseInterval,        CUPSD_VARTYPE_INTEGER },
-#ifdef HAVE_LDAP
-  { "BrowseLDAPBindDN",                &BrowseLDAPBindDN,      CUPSD_VARTYPE_STRING },
-#  ifdef HAVE_LDAP_SSL
-  { "BrowseLDAPCACertFile",    &BrowseLDAPCACertFile,  CUPSD_VARTYPE_PATHNAME },
-#  endif /* HAVE_LDAP_SSL */
-  { "BrowseLDAPDN",            &BrowseLDAPDN,          CUPSD_VARTYPE_STRING },
-  { "BrowseLDAPPassword",      &BrowseLDAPPassword,    CUPSD_VARTYPE_STRING },
-  { "BrowseLDAPServer",                &BrowseLDAPServer,      CUPSD_VARTYPE_STRING },
-#endif /* HAVE_LDAP */
-  { "BrowseLocalOptions",      &BrowseLocalOptions,    CUPSD_VARTYPE_STRING },
-  { "BrowsePort",              &BrowsePort,            CUPSD_VARTYPE_INTEGER },
-  { "BrowseRemoteOptions",     &BrowseRemoteOptions,   CUPSD_VARTYPE_STRING },
-  { "BrowseShortNames",                &BrowseShortNames,      CUPSD_VARTYPE_BOOLEAN },
-  { "BrowseTimeout",           &BrowseTimeout,         CUPSD_VARTYPE_INTEGER },
   { "BrowseWebIF",             &BrowseWebIF,           CUPSD_VARTYPE_BOOLEAN },
   { "Browsing",                        &Browsing,              CUPSD_VARTYPE_BOOLEAN },
   { "CacheDir",                        &CacheDir,              CUPSD_VARTYPE_STRING },
@@ -123,9 +108,6 @@ static const cupsd_var_t    variables[] =
   { "FilterLimit",             &FilterLimit,           CUPSD_VARTYPE_INTEGER },
   { "FilterNice",              &FilterNice,            CUPSD_VARTYPE_INTEGER },
   { "FontPath",                        &FontPath,              CUPSD_VARTYPE_STRING },
-  { "HideImplicitMembers",     &HideImplicitMembers,   CUPSD_VARTYPE_BOOLEAN },
-  { "ImplicitClasses",         &ImplicitClasses,       CUPSD_VARTYPE_BOOLEAN },
-  { "ImplicitAnyClasses",      &ImplicitAnyClasses,    CUPSD_VARTYPE_BOOLEAN },
   { "JobKillDelay",            &JobKillDelay,          CUPSD_VARTYPE_INTEGER },
   { "JobRetryLimit",           &JobRetryLimit,         CUPSD_VARTYPE_INTEGER },
   { "JobRetryInterval",                &JobRetryInterval,      CUPSD_VARTYPE_INTEGER },
@@ -183,7 +165,6 @@ static const cupsd_var_t    variables[] =
 #endif /* HAVE_AUTHORIZATION_H */
   { "TempDir",                 &TempDir,               CUPSD_VARTYPE_PATHNAME },
   { "Timeout",                 &Timeout,               CUPSD_VARTYPE_INTEGER },
-  { "UseNetworkDefault",       &UseNetworkDefault,     CUPSD_VARTYPE_BOOLEAN },
   { "WebInterface",            &WebInterface,          CUPSD_VARTYPE_BOOLEAN }
 };
 #define NUM_VARS       (sizeof(variables) / sizeof(variables[0]))
@@ -451,31 +432,6 @@ cupsdReadConfiguration(void)
 
   cupsdDeleteAllLocations();
 
-  if (NumBrowsers > 0)
-  {
-    free(Browsers);
-    Browsers = NULL;
-
-    NumBrowsers = 0;
-  }
-
-  if (NumPolled > 0)
-  {
-    free(Polled);
-
-    NumPolled = 0;
-  }
-
-  if (NumRelays > 0)
-  {
-    for (i = 0; i < NumRelays; i ++)
-      cupsArrayDelete(Relays[i].from);
-
-    free(Relays);
-
-    NumRelays = 0;
-  }
-
   cupsdDeleteAllListeners();
 
   old_remote_port = RemotePort;
@@ -618,9 +574,6 @@ cupsdReadConfiguration(void)
   FilterLimit              = 0;
   FilterNice               = 0;
   HostNameLookups          = FALSE;
-  ImplicitClasses          = CUPS_DEFAULT_IMPLICIT_CLASSES;
-  ImplicitAnyClasses       = FALSE;
-  HideImplicitMembers      = TRUE;
   KeepAlive                = TRUE;
   KeepAliveTimeout         = DEFAULT_KEEPALIVE;
   ListenBackLog            = SOMAXCONN;
@@ -639,12 +592,7 @@ cupsdReadConfiguration(void)
   NumSystemGroups          = 0;
   WebInterface             = CUPS_DEFAULT_WEBIF;
 
-  BrowseInterval           = DEFAULT_INTERVAL;
-  BrowsePort               = ippPort();
   BrowseLocalProtocols     = parse_protocols(CUPS_DEFAULT_BROWSE_LOCAL_PROTOCOLS);
-  BrowseRemoteProtocols    = parse_protocols(CUPS_DEFAULT_BROWSE_REMOTE_PROTOCOLS);
-  BrowseShortNames         = CUPS_DEFAULT_BROWSE_SHORT_NAMES;
-  BrowseTimeout            = DEFAULT_TIMEOUT;
   BrowseWebIF              = FALSE;
   Browsing                 = CUPS_DEFAULT_BROWSING;
   DefaultShared            = CUPS_DEFAULT_DEFAULT_SHARED;
@@ -656,21 +604,8 @@ cupsdReadConfiguration(void)
   cupsdSetString(&LPDConfigFile, CUPS_DEFAULT_LPD_CONFIG_FILE);
   cupsdSetString(&SMBConfigFile, CUPS_DEFAULT_SMB_CONFIG_FILE);
 
-  cupsdClearString(&BrowseLocalOptions);
-  cupsdClearString(&BrowseRemoteOptions);
-
   cupsdSetString(&ErrorPolicy, "stop-printer");
 
-#ifdef HAVE_LDAP
-  cupsdClearString(&BrowseLDAPBindDN);
-  cupsdClearString(&BrowseLDAPDN);
-  cupsdClearString(&BrowseLDAPPassword);
-  cupsdClearString(&BrowseLDAPServer);
-#  ifdef HAVE_LDAP_SSL
-  cupsdClearString(&BrowseLDAPCACertFile);
-#  endif /* HAVE_LDAP_SSL */
-#endif /* HAVE_LDAP */
-
   JobHistory          = DEFAULT_HISTORY;
   JobFiles            = DEFAULT_FILES;
   JobAutoPurge        = 0;
@@ -832,12 +767,6 @@ cupsdReadConfiguration(void)
     }
   }
 
- /*
-  * Get the access control list for browsing...
-  */
-
-  BrowseACL = cupsdFindLocation("CUPS_INTERNAL_BROWSE_ACL");
-
  /*
   * Open the system log for cupsd if necessary...
   */
@@ -1150,24 +1079,6 @@ cupsdReadConfiguration(void)
                   "Allowing up to %d client connections per host.",
                   MaxClientsPerHost);
 
- /*
-  * Make sure that BrowseTimeout is at least twice the interval...
-  */
-
-  if (BrowseTimeout < (2 * BrowseInterval) || BrowseTimeout <= 0)
-  {
-    cupsdLogMessage(CUPSD_LOG_ALERT, "Invalid BrowseTimeout value %d.",
-                    BrowseTimeout);
-
-    if (BrowseInterval)
-      BrowseTimeout = BrowseInterval * 2;
-    else
-      BrowseTimeout = DEFAULT_TIMEOUT;
-
-    cupsdLogMessage(CUPSD_LOG_ALERT, "Reset BrowseTimeout to %d.",
-                    BrowseTimeout);
-  }
-
  /*
   * Update the default policy, as needed...
   */
@@ -1472,7 +1383,6 @@ cupsdReadConfiguration(void)
 
     cupsdLoadAllPrinters();
     cupsdLoadAllClasses();
-    cupsdLoadRemoteCache();
 
     cupsdCreateCommonData();
 
@@ -2469,20 +2379,10 @@ parse_protocols(const char *s)          /* I - Space-delimited protocols */
     * Add the protocol to the bitmask...
     */
 
-    if (!_cups_strcasecmp(valstart, "cups"))
-      protocols |= BROWSE_CUPS;
-    else if (!_cups_strcasecmp(valstart, "slp"))
-      protocols |= BROWSE_SLP;
-    else if (!_cups_strcasecmp(valstart, "ldap"))
-      protocols |= BROWSE_LDAP;
-    else if (!_cups_strcasecmp(valstart, "dnssd") ||
-             !_cups_strcasecmp(valstart, "dns-sd") ||
-             !_cups_strcasecmp(valstart, "bonjour"))
+    if (!_cups_strcasecmp(valstart, "dnssd") ||
+       !_cups_strcasecmp(valstart, "dns-sd") ||
+       !_cups_strcasecmp(valstart, "bonjour"))
       protocols |= BROWSE_DNSSD;
-    else if (!_cups_strcasecmp(valstart, "lpd"))
-      protocols |= BROWSE_LPD;
-    else if (!_cups_strcasecmp(valstart, "smb"))
-      protocols |= BROWSE_SMB;
     else if (!_cups_strcasecmp(valstart, "all"))
       protocols |= BROWSE_ALL;
     else if (_cups_strcasecmp(valstart, "none"))
@@ -2511,18 +2411,12 @@ read_configuration(cups_file_t *fp)     /* I - File to read from */
                                        /* Line from file */
                        temp[HTTP_MAX_BUFFER],
                                        /* Temporary buffer for value */
-                       *ptr,           /* Pointer into line/temp */
                        *value,         /* Pointer to value */
                        *valueptr;      /* Pointer into value */
   int                  valuelen;       /* Length of value */
   cupsd_var_t const    *var;           /* Current variable */
   http_addrlist_t      *addrlist,      /* Address list */
                        *addr;          /* Current address */
-  unsigned             ip[4],          /* Address value */
-                       mask[4];        /* Netmask value */
-  cupsd_dirsvc_relay_t *relay;         /* Relay data */
-  cupsd_dirsvc_poll_t  *pollp;         /* Polling data */
-  cupsd_location_t     *location;      /* Browse location */
   cups_file_t          *incfile;       /* Include file */
   char                 incname[1024];  /* Include filename */
   struct group         *group;         /* Group */
@@ -2706,117 +2600,12 @@ read_configuration(cups_file_t *fp)    /* I - File to read from */
 
       httpAddrFreeList(addrlist);
     }
-    else if (!_cups_strcasecmp(line, "BrowseAddress") && value)
-    {
-     /*
-      * Add a browse address to the list...
-      */
-
-      cupsd_dirsvc_addr_t      *dira;  /* New browse address array */
-
-
-      if (NumBrowsers == 0)
-        dira = malloc(sizeof(cupsd_dirsvc_addr_t));
-      else
-        dira = realloc(Browsers, (NumBrowsers + 1) * sizeof(cupsd_dirsvc_addr_t));
-
-      if (!dira)
-      {
-        cupsdLogMessage(CUPSD_LOG_ERROR,
-                       "Unable to allocate BrowseAddress at line %d - %s.",
-                       linenum, strerror(errno));
-        continue;
-      }
-
-      Browsers = dira;
-      dira     += NumBrowsers;
-
-      memset(dira, 0, sizeof(cupsd_dirsvc_addr_t));
-
-      if (!_cups_strcasecmp(value, "@LOCAL"))
-      {
-       /*
-       * Send browse data to all local interfaces...
-       */
-
-       strcpy(dira->iface, "*");
-       NumBrowsers ++;
-      }
-      else if (!_cups_strncasecmp(value, "@IF(", 4))
-      {
-       /*
-       * Send browse data to the named interface...
-       */
-
-       strlcpy(dira->iface, value + 4, sizeof(Browsers[0].iface));
-
-        ptr = dira->iface + strlen(dira->iface) - 1;
-        if (*ptr == ')')
-         *ptr = '\0';
-
-       NumBrowsers ++;
-      }
-      else if ((addrlist = get_address(value, BrowsePort)) != NULL)
-      {
-       /*
-        * Only IPv4 addresses are supported...
-        */
-
-       for (addr = addrlist; addr; addr = addr->next)
-         if (_httpAddrFamily(&(addr->addr)) == AF_INET)
-           break;
-
-       if (addr)
-       {
-         memcpy(&(dira->to), &(addrlist->addr), sizeof(dira->to));
-         httpAddrString(&(dira->to), temp, sizeof(temp));
-
-         cupsdLogMessage(CUPSD_LOG_INFO,
-                         "Sending browsing info to %s:%d (IPv4)",
-                         temp, _httpAddrPort(&(dira->to)));
-
-         NumBrowsers ++;
-       }
-       else
-         cupsdLogMessage(CUPSD_LOG_ERROR, "Bad BrowseAddress %s at line %d.",
-                         value, linenum);
-
-       httpAddrFreeList(addrlist);
-      }
-      else
-        cupsdLogMessage(CUPSD_LOG_ERROR, "Bad BrowseAddress %s at line %d.",
-                       value, linenum);
-    }
-    else if (!_cups_strcasecmp(line, "BrowseOrder") && value)
-    {
-     /*
-      * "BrowseOrder Deny,Allow" or "BrowseOrder Allow,Deny"...
-      */
-
-      if ((location = cupsdFindLocation("CUPS_INTERNAL_BROWSE_ACL")) == NULL)
-        if ((location = cupsdNewLocation("CUPS_INTERNAL_BROWSE_ACL")) != NULL)
-         cupsdAddLocation(location);
-
-      if (location == NULL)
-        cupsdLogMessage(CUPSD_LOG_ERROR,
-                       "Unable to initialize browse access control list.");
-      else if (!_cups_strncasecmp(value, "deny", 4))
-        location->order_type = CUPSD_AUTH_ALLOW;
-      else if (!_cups_strncasecmp(value, "allow", 5))
-        location->order_type = CUPSD_AUTH_DENY;
-      else
-        cupsdLogMessage(CUPSD_LOG_ERROR,
-                       "Unknown BrowseOrder value %s on line %d.",
-                       value, linenum);
-    }
     else if (!_cups_strcasecmp(line, "BrowseProtocols") ||
-             !_cups_strcasecmp(line, "BrowseLocalProtocols") ||
-             !_cups_strcasecmp(line, "BrowseRemoteProtocols"))
+             !_cups_strcasecmp(line, "BrowseLocalProtocols"))
     {
      /*
       * "BrowseProtocols name [... name]"
       * "BrowseLocalProtocols name [... name]"
-      * "BrowseRemoteProtocols name [... name]"
       */
 
       int protocols = parse_protocols(value);
@@ -2829,367 +2618,7 @@ read_configuration(cups_file_t *fp)     /* I - File to read from */
         break;
       }
 
-      if (_cups_strcasecmp(line, "BrowseLocalProtocols"))
-        BrowseRemoteProtocols = protocols;
-      if (_cups_strcasecmp(line, "BrowseRemoteProtocols"))
-        BrowseLocalProtocols = protocols;
-    }
-    else if ((!_cups_strcasecmp(line, "BrowseAllow") ||
-              !_cups_strcasecmp(line, "BrowseDeny")) && value)
-    {
-     /*
-      * BrowseAllow [From] host/ip...
-      * BrowseDeny [From] host/ip...
-      */
-
-      if ((location = cupsdFindLocation("CUPS_INTERNAL_BROWSE_ACL")) == NULL)
-        if ((location = cupsdNewLocation("CUPS_INTERNAL_BROWSE_ACL")) != NULL)
-         cupsdAddLocation(location);
-
-
-      if (location == NULL)
-        cupsdLogMessage(CUPSD_LOG_ERROR,
-                       "Unable to initialize browse access control list.");
-      else
-      {
-       if (!_cups_strncasecmp(value, "from", 4))
-       {
-        /*
-         * Skip leading "from"...
-         */
-
-         value += 4;
-       }
-
-       while (*value)
-       {
-        /*
-         * Skip leading whitespace...
-         */
-
-         while (_cups_isspace(*value))
-           value ++;
-
-         if (!*value)
-           break;
-
-        /*
-         * Find the end of the value...
-         */
-
-         for (valueptr = value;
-              *valueptr && !_cups_isspace(*valueptr);
-              valueptr ++);
-
-         while (_cups_isspace(*valueptr))
-           *valueptr++ = '\0';
-
-        /*
-         * Figure out what form the allow/deny address takes:
-         *
-         *    All
-         *    None
-         *    *.domain.com
-         *    .domain.com
-         *    host.domain.com
-         *    nnn.*
-         *    nnn.nnn.*
-         *    nnn.nnn.nnn.*
-         *    nnn.nnn.nnn.nnn
-         *    nnn.nnn.nnn.nnn/mm
-         *    nnn.nnn.nnn.nnn/mmm.mmm.mmm.mmm
-         */
-
-         if (!_cups_strcasecmp(value, "all"))
-         {
-          /*
-           * All hosts...
-           */
-
-           if (!_cups_strcasecmp(line, "BrowseAllow"))
-             cupsdAddIPMask(&(location->allow), zeros, zeros);
-           else
-             cupsdAddIPMask(&(location->deny), zeros, zeros);
-         }
-         else if (!_cups_strcasecmp(value, "none"))
-         {
-          /*
-           * No hosts...
-           */
-
-           if (!_cups_strcasecmp(line, "BrowseAllow"))
-             cupsdAddIPMask(&(location->allow), ones, zeros);
-           else
-             cupsdAddIPMask(&(location->deny), ones, zeros);
-         }
-#ifdef AF_INET6
-         else if (value[0] == '*' || value[0] == '.' ||
-                  (!isdigit(value[0] & 255) && value[0] != '['))
-#else
-         else if (value[0] == '*' || value[0] == '.' ||
-                  !isdigit(value[0] & 255))
-#endif /* AF_INET6 */
-         {
-          /*
-           * Host or domain name...
-           */
-
-           if (!_cups_strcasecmp(line, "BrowseAllow"))
-             cupsdAddNameMask(&(location->allow), value);
-           else
-             cupsdAddNameMask(&(location->deny), value);
-         }
-         else
-         {
-          /*
-           * One of many IP address forms...
-           */
-
-           if (!get_addr_and_mask(value, ip, mask))
-           {
-             cupsdLogMessage(CUPSD_LOG_ERROR, "Bad netmask value %s on line %d.",
-                             value, linenum);
-             break;
-           }
-
-           if (!_cups_strcasecmp(line, "BrowseAllow"))
-             cupsdAddIPMask(&(location->allow), ip, mask);
-           else
-             cupsdAddIPMask(&(location->deny), ip, mask);
-         }
-
-        /*
-         * Advance to next value...
-         */
-
-         value = valueptr;
-       }
-      }
-    }
-    else if (!_cups_strcasecmp(line, "BrowseRelay") && value)
-    {
-     /*
-      * BrowseRelay [from] source [to] destination
-      */
-
-      if (NumRelays == 0)
-        relay = malloc(sizeof(cupsd_dirsvc_relay_t));
-      else
-        relay = realloc(Relays, (NumRelays + 1) * sizeof(cupsd_dirsvc_relay_t));
-
-      if (!relay)
-      {
-        cupsdLogMessage(CUPSD_LOG_ERROR,
-                       "Unable to allocate BrowseRelay at line %d - %s.",
-                       linenum, strerror(errno));
-        continue;
-      }
-
-      Relays = relay;
-      relay  += NumRelays;
-
-      memset(relay, 0, sizeof(cupsd_dirsvc_relay_t));
-
-      if (!_cups_strncasecmp(value, "from ", 5))
-      {
-       /*
-       * Skip leading "from"...
-       */
-
-       value += 5;
-
-       /*
-        * Skip leading whitespace...
-       */
-
-       while (_cups_isspace(*value))
-         value ++;
-      }
-
-     /*
-      * Find the end of the from value...
-      */
-
-      for (valueptr = value;
-          *valueptr && !_cups_isspace(*valueptr);
-          valueptr ++);
-
-      while (_cups_isspace(*valueptr))
-       *valueptr++ = '\0';
-
-     /*
-      * Figure out what form the from address takes:
-      *
-      *    *.domain.com
-      *    .domain.com
-      *    host.domain.com
-      *    nnn.*
-      *    nnn.nnn.*
-      *    nnn.nnn.nnn.*
-      *    nnn.nnn.nnn.nnn
-      *    nnn.nnn.nnn.nnn/mm
-      *    nnn.nnn.nnn.nnn/mmm.mmm.mmm.mmm
-      */
-
-#ifdef AF_INET6
-      if (value[0] == '*' || value[0] == '.' ||
-          (!isdigit(value[0] & 255) && value[0] != '['))
-#else
-      if (value[0] == '*' || value[0] == '.' || !isdigit(value[0] & 255))
-#endif /* AF_INET6 */
-      {
-       /*
-        * Host or domain name...
-       */
-
-        if (!cupsdAddNameMask(&(relay->from), value))
-       {
-         cupsdLogMessage(CUPSD_LOG_ERROR,
-                         "Unable to allocate BrowseRelay name at line %d - %s.",
-                         linenum, strerror(errno));
-         continue;
-       }
-      }
-      else
-      {
-       /*
-        * One of many IP address forms...
-       */
-
-        if (!get_addr_and_mask(value, ip, mask))
-       {
-          cupsdLogMessage(CUPSD_LOG_ERROR, "Bad netmask value %s on line %d.",
-                         value, linenum);
-         break;
-       }
-
-        if (!cupsdAddIPMask(&(relay->from), ip, mask))
-       {
-         cupsdLogMessage(CUPSD_LOG_ERROR,
-                         "Unable to allocate BrowseRelay IP at line %d - %s.",
-                         linenum, strerror(errno));
-         continue;
-       }
-      }
-
-     /*
-      * Get "to" address and port...
-      */
-
-      if (!_cups_strncasecmp(valueptr, "to ", 3))
-      {
-       /*
-        * Strip leading "to"...
-       */
-
-       valueptr += 3;
-
-       while (_cups_isspace(*valueptr))
-         valueptr ++;
-      }
-
-      if ((addrlist = get_address(valueptr, BrowsePort)) != NULL)
-      {
-       /*
-        * Only IPv4 addresses are supported...
-        */
-
-       for (addr = addrlist; addr; addr = addr->next)
-         if (addr->addr.addr.sa_family == AF_INET)
-           break;
-
-       if (addr)
-       {
-         memcpy(&(relay->to), &(addrlist->addr), sizeof(relay->to));
-
-         httpAddrString(&(relay->to), temp, sizeof(temp));
-
-         cupsdLogMessage(CUPSD_LOG_INFO, "Relaying from %s to %s:%d (IPv4)",
-                         value, temp, _httpAddrPort(&(relay->to)));
-
-         NumRelays ++;
-       }
-       else
-       {
-         cupsArrayDelete(relay->from);
-         relay->from = NULL;
-
-         cupsdLogMessage(CUPSD_LOG_ERROR, "Bad relay address %s at line %d.",
-                         valueptr, linenum);
-       }
-
-       httpAddrFreeList(addrlist);
-      }
-      else
-      {
-       cupsArrayDelete(relay->from);
-       relay->from = NULL;
-
-        cupsdLogMessage(CUPSD_LOG_ERROR, "Bad relay address %s at line %d.",
-                       valueptr, linenum);
-      }
-    }
-    else if (!_cups_strcasecmp(line, "BrowsePoll") && value)
-    {
-     /*
-      * BrowsePoll address[:port]
-      */
-
-      char             *portname;      /* Port name */
-      int              portnum;        /* Port number */
-      struct servent   *service;       /* Service */
-
-
-     /*
-      * Extract the port name from the address...
-      */
-
-      if ((portname = strrchr(value, ':')) != NULL && !strchr(portname, ']'))
-      {
-        *portname++ = '\0';
-
-        if (isdigit(*portname & 255))
-         portnum = atoi(portname);
-       else if ((service = getservbyname(portname, NULL)) != NULL)
-         portnum = ntohs(service->s_port);
-       else
-       {
-         cupsdLogMessage(CUPSD_LOG_ERROR, "Lookup of service \"%s\" failed.",
-                         portname);
-          continue;
-       }
-      }
-      else
-        portnum = ippPort();
-
-     /*
-      * Add the poll entry...
-      */
-
-      if (NumPolled == 0)
-        pollp = malloc(sizeof(cupsd_dirsvc_poll_t));
-      else
-        pollp = realloc(Polled, (NumPolled + 1) * sizeof(cupsd_dirsvc_poll_t));
-
-      if (!pollp)
-      {
-        cupsdLogMessage(CUPSD_LOG_ERROR,
-                       "Unable to allocate BrowsePoll at line %d - %s.",
-                       linenum, strerror(errno));
-        continue;
-      }
-
-      Polled = pollp;
-      pollp   += NumPolled;
-
-      NumPolled ++;
-      memset(pollp, 0, sizeof(cupsd_dirsvc_poll_t));
-
-      strlcpy(pollp->hostname, value, sizeof(pollp->hostname));
-      pollp->port = portnum;
-
-      cupsdLogMessage(CUPSD_LOG_INFO, "Polling %s:%d", pollp->hostname,
-                     pollp->port);
+      BrowseLocalProtocols = protocols;
     }
     else if (!_cups_strcasecmp(line, "DefaultAuthType") && value)
     {
index a68c31d3bc98d819de1f378825f838e65e6cfab8..4a0b5961e6d16e3b14dc4be79b2aab2efb010fd9 100644 (file)
@@ -193,12 +193,6 @@ VAR int                    MaxClients              VALUE(100),
                                        /* Support the Keep-Alive option? */
                        KeepAliveTimeout        VALUE(DEFAULT_KEEPALIVE),
                                        /* Timeout between requests */
-                       ImplicitClasses         VALUE(TRUE),
-                                       /* Are classes implicitly created? */
-                       ImplicitAnyClasses      VALUE(FALSE),
-                                       /* Create AnyPrinter classes? */
-                       HideImplicitMembers     VALUE(TRUE),
-                                       /* Hide implicit class members? */
                        FileDevice              VALUE(FALSE),
                                        /* Allow file: devices? */
                        FilterLimit             VALUE(0),
index 714871c85e15ecffa92171e194c79176f0253ecb..2fa741e914362acaafa7fcd0fd24031744437276 100644 (file)
@@ -1774,7 +1774,8 @@ load_ppds(const char *d,          /* I - Actual directory */
                product[256],           /* Product */
                psversion[256],         /* PSVersion */
                temp[512];              /* Temporary make and model */
-  int          model_number,           /* cupsModelNumber */
+  int          install_group,          /* In the installable options group? */
+               model_number,           /* cupsModelNumber */
                type;                   /* ppd-type */
   cups_array_t *products,              /* Product array */
                *psversions,            /* PSVersion array */
@@ -1998,6 +1999,7 @@ load_ppds(const char *d,          /* I - Actual directory */
     lang_encoding[0] = '\0';
     strcpy(lang_version, "en");
     model_number     = 0;
+    install_group    = 0;
     type             = PPD_TYPE_POSTSCRIPT;
 
     while (cupsFileGets(fp, line, sizeof(line)) != NULL)
@@ -2092,15 +2094,19 @@ load_ppds(const char *d,                /* I - Actual directory */
       }
       else if (!strncmp(line, "*cupsModelNumber:", 17))
         sscanf(line, "*cupsModelNumber:%d", &model_number);
+      else if (!strncmp(line, "*OpenGroup: Installable", 23))
+        install_group = 1;
+      else if (!strncmp(line, "*CloseGroup:", 12))
+        install_group = 0;
       else if (!strncmp(line, "*OpenUI", 7))
       {
        /*
         * Stop early if we have a NickName or ModelName attributes
-       * before the first OpenUI...
+       * before the first non-installable OpenUI...
        */
 
-        if ((model_name[0] || nick_name[0]) && cupsArrayCount(products) > 0 &&
-           cupsArrayCount(psversions) > 0)
+        if (!install_group && (model_name[0] || nick_name[0]) &&
+            cupsArrayCount(products) > 0 && cupsArrayCount(psversions) > 0)
          break;
       }
     }
diff --git a/scheduler/cups-polld.c b/scheduler/cups-polld.c
deleted file mode 100644 (file)
index 35ac250..0000000
+++ /dev/null
@@ -1,469 +0,0 @@
-/*
- * "$Id: cups-polld.c 7198 2008-01-08 00:12:17Z mike $"
- *
- *   Polling daemon for CUPS.
- *
- *   Copyright 2007-2011 by Apple Inc.
- *   Copyright 1997-2006 by Easy Software Products, all rights reserved.
- *
- *   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
- *   file is missing or damaged, see the license at "http://www.cups.org/".
- *
- * Contents:
- *
- *   main()           - Open sockets and poll until we are killed...
- *   dequote()        - Remote quotes from a string.
- *   poll_server()    - Poll the server for the given set of printers or
- *                      classes.
- *   sighup_handler() - Handle 'hangup' signals to restart polling.
- */
-
-/*
- * Include necessary headers...
- */
-
-#include <cups/cups-private.h>
-#include <signal.h>
-
-
-/*
- * Local globals...
- */
-
-static int     restart_polling = 1;
-
-
-/*
- * Local functions...
- */
-
-static char    *dequote(char *d, const char *s, int dlen);
-static int     poll_server(http_t *http, int sock, int port, int interval,
-                           const char *prefix);
-static void    sighup_handler(int sig);
-
-
-/*
- * 'main()' - Open sockets and poll until we are killed...
- */
-
-int                                    /* O - Exit status */
-main(int  argc,                                /* I - Number of command-line args */
-     char *argv[])                     /* I - Command-line arguments */
-{
-  http_t       *http;                  /* HTTP connection */
-  int          interval;               /* Polling interval */
-  int          sock;                   /* Browser sock */
-  int          port;                   /* Browser port */
-  int          val;                    /* Socket option value */
-  int          seconds,                /* Seconds left from poll */
-               remain;                 /* Total remaining time to sleep */
-  char         prefix[1024];           /* Prefix for log messages */
-#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
-  struct sigaction action;             /* Actions for POSIX signals */
-#endif /* HAVE_SIGACTION && !HAVE_SIGSET */
-
-
- /*
-  * Catch hangup signals for when the network changes...
-  */
-
-#ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */
-  sigset(SIGHUP, sighup_handler);
-#elif defined(HAVE_SIGACTION)
-  memset(&action, 0, sizeof(action));
-
-  sigemptyset(&action.sa_mask);
-  sigaddset(&action.sa_mask, SIGHUP);
-  action.sa_handler = sighup_handler;
-  sigaction(SIGHUP, &action, NULL);
-#else
-  signal(SIGHUP, sighup_handler);
-#endif /* HAVE_SIGSET */
-
- /*
-  * Don't buffer log messages...
-  */
-
-  setbuf(stderr, NULL);
-
- /*
-  * The command-line must contain the following:
-  *
-  *    cups-polld server server-port interval port
-  */
-
-  if (argc != 5)
-  {
-    fputs("Usage: cups-polld server server-port interval port\n", stderr);
-    return (1);
-  }
-
-  interval = atoi(argv[3]);
-  port     = atoi(argv[4]);
-
-  if (interval < 2)
-    interval = 2;
-
-  snprintf(prefix, sizeof(prefix), "[cups-polld %s:%d]", argv[1], atoi(argv[2]));
-
- /*
-  * Open a broadcast socket...
-  */
-
-  if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
-  {
-    fprintf(stderr, "ERROR: %s Unable to open broadcast socket: %s\n", prefix,
-            strerror(errno));
-    return (1);
-  }
-
- /*
-  * Set the "broadcast" flag...
-  */
-
-  val = 1;
-  if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &val, sizeof(val)))
-  {
-    fprintf(stderr, "ERROR: %s Unable to put socket in broadcast mode: %s\n",
-            prefix, strerror(errno));
-
-    close(sock);
-    return (1);
-  }
-
- /*
-  * Loop forever, asking for available printers and classes...
-  */
-
-  for (http = NULL; !ferror(stderr);)
-  {
-   /*
-    * Open a connection to the server...
-    */
-
-    if (restart_polling || !http)
-    {
-      restart_polling = 0;
-      httpClose(http);
-
-      if ((http = httpConnectEncrypt(argv[1], atoi(argv[2]),
-                                     cupsEncryption())) == NULL)
-      {
-       fprintf(stderr, "ERROR: %s Unable to connect to %s on port %s.\n",
-               prefix, argv[1], argv[2]);
-      }
-    }
-
-   /*
-    * Get the printers and classes...
-    */
-
-    remain = interval;
-
-    if (http && (seconds = poll_server(http, sock, port, interval, prefix)) > 0)
-      remain -= seconds;
-
-   /*
-    * Sleep for any remaining time...
-    */
-
-    if (remain > 0 && !restart_polling)
-      sleep(remain);
-  }
-
-  return (1);
-}
-
-
-/*
- * 'dequote()' - Remote quotes from a string.
- */
-
-static char *                          /* O - Dequoted string */
-dequote(char       *d,                 /* I - Destination string */
-        const char *s,                 /* I - Source string */
-       int        dlen)                /* I - Destination length */
-{
-  char *dptr;                          /* Pointer into destination */
-
-
-  if (s)
-  {
-    for (dptr = d, dlen --; *s && dlen > 0; s ++)
-      if (*s != '\"')
-      {
-       *dptr++ = *s;
-       dlen --;
-      }
-
-    *dptr = '\0';
-  }
-  else
-    *d = '\0';
-
-  return (d);
-}
-
-
-/*
- * 'poll_server()' - Poll the server for the given set of printers or classes.
- */
-
-static int                             /* O - Number of seconds or -1 on error */
-poll_server(http_t      *http,         /* I - HTTP connection */
-           int         sock,           /* I - Broadcast sock */
-           int         port,           /* I - Broadcast port */
-           int         interval,       /* I - Polling interval */
-           const char  *prefix)        /* I - Prefix for log messages */
-{
-  int                  seconds;        /* Number of seconds */
-  int                  count,          /* Current number of printers/classes */
-                       max_count;      /* Maximum printers/classes per second */
-  ipp_t                        *request,       /* Request data */
-                       *response;      /* Response data */
-  ipp_attribute_t      *attr;          /* Current attribute */
-  const char           *uri;           /* printer-uri */
-  char                 info[1024],     /* printer-info */
-                       job_sheets[1024],/* job-sheets-default */
-                       location[1024], /* printer-location */
-                       make_model[1024];
-                                       /* printer-make-and-model */
-  cups_ptype_t         type;           /* printer-type */
-  ipp_pstate_t         state;          /* printer-state */
-  int                  accepting;      /* printer-is-accepting-jobs */
-  struct sockaddr_in   addr;           /* Broadcast address */
-  char                 packet[1540];   /* Data packet */
-  static const char * const attrs[] =  /* Requested attributes */
-                       {
-                         "job-sheets-default",
-                         "printer-info",
-                         "printer-is-accepting-jobs",
-                         "printer-location",
-                         "printer-make-and-model",
-                         "printer-name",
-                         "printer-state",
-                         "printer-type",
-                         "printer-uri-supported"
-                       };
-
-
- /*
-  * Broadcast to 127.0.0.1 (localhost)
-  */
-
-  memset(&addr, 0, sizeof(addr));
-  addr.sin_addr.s_addr = htonl(0x7f000001);
-  addr.sin_family      = AF_INET;
-  addr.sin_port        = htons(port);
-
- /*
-  * Build a CUPS_GET_PRINTERS request and pass along a list of the
-  * attributes we are interested in along with the types of printers
-  * (and classes) we want.
-  */
-
-  request = ippNewRequest(CUPS_GET_PRINTERS);
-
-  ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
-               "requested-attributes", sizeof(attrs) / sizeof(attrs[0]),
-              NULL, attrs);
-
-  ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_ENUM,
-                "printer-type", 0);
-  ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_ENUM,
-                "printer-type-mask",
-               CUPS_PRINTER_REMOTE | CUPS_PRINTER_IMPLICIT |
-               CUPS_PRINTER_NOT_SHARED);
-
- /*
-  * Do the request and get back a response...
-  */
-
-  seconds  = time(NULL);
-  response = cupsDoRequest(http, request, "/");
-
-  if (cupsLastError() > IPP_OK_CONFLICT)
-  {
-    fprintf(stderr, "ERROR: %s CUPS-Get-Printers failed: %s\n", prefix,
-            cupsLastErrorString());
-    ippDelete(response);
-    return (-1);
-  }
-
-  if (response)
-  {
-   /*
-    * Figure out how many printers/classes we have...
-    */
-
-    for (attr = ippFindAttribute(response, "printer-name", IPP_TAG_NAME),
-             max_count = 0;
-        attr != NULL;
-        attr = ippFindNextAttribute(response, "printer-name", IPP_TAG_NAME),
-            max_count ++);
-
-    fprintf(stderr, "DEBUG: %s Found %d printers.\n", prefix, max_count);
-
-    count     = 0;
-    max_count = 2 * max_count / interval + 1;
-
-   /*
-    * Loop through the printers or classes returned in the list...
-    */
-
-    for (attr = response->attrs; attr; attr = attr->next)
-    {
-     /*
-      * Skip leading attributes until we hit a printer...
-      */
-
-      while (attr && attr->group_tag != IPP_TAG_PRINTER)
-        attr = attr->next;
-
-      if (!attr)
-        break;
-
-     /*
-      * Pull the needed attributes from this printer...
-      */
-
-      uri           = NULL;
-      info[0]       = '\0';
-      job_sheets[0] = '\0';
-      location[0]   = '\0';
-      make_model[0] = '\0';
-      type          = CUPS_PRINTER_REMOTE;
-      accepting     = 1;
-      state         = IPP_PRINTER_IDLE;
-
-      while (attr != NULL && attr->group_tag == IPP_TAG_PRINTER)
-      {
-        if (!strcmp(attr->name, "job-sheets-default") &&
-           (attr->value_tag == IPP_TAG_NAME ||
-            attr->value_tag == IPP_TAG_KEYWORD))
-       {
-         if (attr->num_values == 1)
-           snprintf(job_sheets, sizeof(job_sheets), " job-sheets=%s",
-                    attr->values[0].string.text);
-          else
-           snprintf(job_sheets, sizeof(job_sheets), " job-sheets=%s,%s",
-                    attr->values[0].string.text,
-                    attr->values[1].string.text);
-       }
-        else if (!strcmp(attr->name, "printer-uri-supported") &&
-                attr->value_tag == IPP_TAG_URI)
-         uri = attr->values[0].string.text;
-        else if (!strcmp(attr->name, "printer-info") &&
-                attr->value_tag == IPP_TAG_TEXT)
-         dequote(info, attr->values[0].string.text, sizeof(info));
-        else if (!strcmp(attr->name, "printer-is-accepting-jobs") &&
-                attr->value_tag == IPP_TAG_BOOLEAN)
-         accepting = attr->values[0].boolean;
-        else if (!strcmp(attr->name, "printer-location") &&
-                attr->value_tag == IPP_TAG_TEXT)
-         dequote(location, attr->values[0].string.text, sizeof(location));
-        else if (!strcmp(attr->name, "printer-make-and-model") &&
-                attr->value_tag == IPP_TAG_TEXT)
-         dequote(make_model, attr->values[0].string.text, sizeof(location));
-        else if (!strcmp(attr->name, "printer-state") &&
-                attr->value_tag == IPP_TAG_ENUM)
-         state = (ipp_pstate_t)attr->values[0].integer;
-        else if (!strcmp(attr->name, "printer-type") &&
-                attr->value_tag == IPP_TAG_ENUM)
-         type = (cups_ptype_t)attr->values[0].integer;
-
-        attr = attr->next;
-      }
-
-     /*
-      * See if we have everything needed...
-      */
-
-      if (uri == NULL)
-      {
-        if (attr == NULL)
-         break;
-       else
-          continue;
-      }
-
-     /*
-      * Send the printer information...
-      */
-
-      type |= CUPS_PRINTER_REMOTE;
-
-      if (!accepting)
-       type |= CUPS_PRINTER_REJECTING;
-
-      snprintf(packet, sizeof(packet),
-               "%x %x %s \"%s\" \"%s\" \"%s\" lease-duration=%d%s\n",
-               type, state, uri, location, info, make_model, interval * 2,
-              job_sheets);
-
-      fprintf(stderr, "DEBUG2: %s Sending %s", prefix, packet);
-
-      if (sendto(sock, packet, strlen(packet), 0,
-                (struct sockaddr *)&addr, sizeof(addr)) <= 0)
-      {
-       ippDelete(response);
-       perror("cups-polld");
-       return (-1);
-      }
-
-     /*
-      * Throttle the local broadcasts as needed so that we don't
-      * overwhelm the local server...
-      */
-
-      count ++;
-      if (count >= max_count)
-      {
-       /*
-       * Sleep for a second...
-       */
-
-       count = 0;
-
-       sleep(1);
-      }
-
-      if (!attr || restart_polling)
-        break;
-    }
-
-    ippDelete(response);
-  }
-
- /*
-  * Return the number of seconds we used...
-  */
-
-  return (time(NULL) - seconds);
-}
-
-
-/*
- * 'sighup_handler()' - Handle 'hangup' signals to restart polling.
- */
-
-static void
-sighup_handler(int sig)                        /* I - Signal number */
-{
-  (void)sig;
-
-  restart_polling = 1;
-
-#if !defined(HAVE_SIGSET) && !defined(HAVE_SIGACTION)
-  signal(SIGHUP, sighup_handler);
-#endif /* !HAVE_SIGSET && !HAVE_SIGACTION */
-}
-
-
-/*
- * End of "$Id: cups-polld.c 7198 2008-01-08 00:12:17Z mike $".
- */
index eb8fd2264435020117a6dd2588f3f7bdcdb2cbe4..05cdb7a100a676fd22351a6c3060bbd21cc69229 100644 (file)
  *
  * Contents:
  *
- *   cupsdDeregisterPrinter()   - Stop sending broadcast information for a local
- *                                printer and remove any pending references to
- *                                remote printers.
- *   cupsdLoadRemoteCache()     - Load the remote printer cache.
- *   cupsdRegisterPrinter()     - Start sending broadcast information for a
- *                                printer or update the broadcast contents.
- *   cupsdRestartPolling()      - Restart polling servers as needed.
- *   cupsdSaveRemoteCache()     - Save the remote printer cache.
- *   cupsdSendBrowseList()      - Send new browsing information as necessary.
- *   ldap_rebind_proc()         - Callback function for LDAP rebind
- *   ldap_connect()             - Start new LDAP connection
- *   ldap_reconnect()           - Reconnect to LDAP Server
- *   ldap_disconnect()          - Disconnect from LDAP Server
- *   cupsdStartBrowsing()       - Start sending and receiving broadcast
- *                                information.
- *   cupsdStartPolling()        - Start polling servers as needed.
- *   cupsdStopBrowsing()        - Stop sending and receiving broadcast
- *                                information.
- *   cupsdStopPolling()         - Stop polling servers as needed.
- *   cupsdUpdateDNSSDName()     - Update the computer name we use for
- *                                browsing...
- *   cupsdUpdateLDAPBrowse()    - Scan for new printers via LDAP...
- *   cupsdUpdateSLPBrowse()     - Get browsing information via SLP.
- *   dequote()                  - Remote quotes from a string.
- *   dnssdAddAlias()            - Add a DNS-SD alias name.
- *   dnssdBuildTxtRecord()      - Build a TXT record from printer info.
- *   dnssdComparePrinters()     - Compare the registered names of two printers.
- *   dnssdDeregisterPrinter()   - Stop sending broadcast information for a
- *                                printer.
- *   dnssdPackTxtRecord()       - Pack an array of key/value pairs into the TXT
- *                                record format.
- *   dnssdRegisterCallback()    - DNSServiceRegister callback.
- *   dnssdRegisterPrinter()     - Start sending broadcast information for a
- *                                printer or update the broadcast contents.
- *   dnssdStop()                - Stop all DNS-SD registrations.
- *   dnssdUpdate()              - Handle DNS-SD queries.
- *   get_auth_info_required()   - Get the auth-info-required value to advertise.
- *   get_hostconfig()           - Get an /etc/hostconfig service setting.
- *   is_local_queue()           - Determine whether the URI points at a local
- *                                queue.
- *   process_browse_data()      - Process new browse data.
- *   process_implicit_classes() - Create/update implicit classes as needed.
- *   send_cups_browse()         - Send new browsing information using the CUPS
- *                                protocol.
- *   ldap_search_rec()          - LDAP Search with reconnect
- *   ldap_freeres()             - Free LDAPMessage
- *   ldap_getval_char()         - Get first LDAP value and convert to string
- *   send_ldap_ou()             - Send LDAP ou registrations.
- *   send_ldap_browse()         - Send LDAP printer registrations.
- *   ldap_dereg_printer()       - Delete printer from directory
- *   ldap_dereg_ou()            - Remove the organizational unit.
- *   send_slp_browse()          - Register the specified printer with SLP.
- *   slp_attr_callback()        - SLP attribute callback
- *   slp_dereg_printer()        - SLPDereg() the specified printer
- *   slp_get_attr()             - Get an attribute from an SLP registration.
- *   slp_reg_callback()         - Empty SLPRegReport.
- *   slp_url_callback()         - SLP service url callback
- *   update_cups_browse()       - Update the browse lists using the CUPS
- *                                protocol.
- *   update_lpd()               - Update the LPD configuration as needed.
- *   update_polling()           - Read status messages from the poll daemons.
- *   update_smb()               - Update the SMB configuration as needed.
+ *   cupsdDeregisterPrinter() - Stop sending broadcast information for a local
+ *                             printer and remove any pending references to
+ *                             remote printers.
+ *   cupsdRegisterPrinter()   - Start sending broadcast information for a
+ *                             printer or update the broadcast contents.
+ *   cupsdStartBrowsing()     - Start sending and receiving broadcast
+ *                             information.
+ *   cupsdStopBrowsing()      - Stop sending and receiving broadcast
+ *                             information.
+ *   cupsdUpdateDNSSDName()   - Update the computer name we use for browsing...
+ *   dnssdAddAlias()         - Add a DNS-SD alias name.
+ *   dnssdBuildTxtRecord()    - Build a TXT record from printer info.
+ *   dnssdDeregisterPrinter() - Stop sending broadcast information for a
+ *                             printer.
+ *   dnssdPackTxtRecord()     - Pack an array of key/value pairs into the TXT
+ *                             record format.
+ *   dnssdRegisterCallback()  - DNSServiceRegister callback.
+ *   dnssdRegisterPrinter()   - Start sending broadcast information for a
+ *                             printer or update the broadcast contents.
+ *   dnssdStop()             - Stop all DNS-SD registrations.
+ *   dnssdUpdate()           - Handle DNS-SD queries.
+ *   get_auth_info_required() - Get the auth-info-required value to advertise.
+ *   get_hostconfig()        - Get an /etc/hostconfig service setting.
+ *   update_lpd()            - Update the LPD configuration as needed.
+ *   update_smb()            - Update the SMB configuration as needed.
  */
 
 /*
  * Local functions...
  */
 
-static char    *dequote(char *d, const char *s, int dlen);
 static char    *get_auth_info_required(cupsd_printer_t *p, char *buffer,
                                        size_t bufsize);
 #ifdef __APPLE__
 static int     get_hostconfig(const char *name);
 #endif /* __APPLE__ */
-static int     is_local_queue(const char *uri, char *host, int hostlen,
-                              char *resource, int resourcelen);
-static void    process_browse_data(const char *uri, const char *host,
-                                   const char *resource, cups_ptype_t type,
-                                   ipp_pstate_t state, const char *location,
-                                   const char *info, const char *make_model,
-                                   int num_attrs, cups_option_t *attrs);
-static void    process_implicit_classes(void);
-static void    send_cups_browse(cupsd_printer_t *p);
-#ifdef HAVE_LDAP
-static LDAP    *ldap_connect(void);
-static LDAP    *ldap_reconnect(void);
-static void    ldap_disconnect(LDAP *ld);
-static int     ldap_search_rec(LDAP *ld, char *base, int scope,
-                                char *filter, char *attrs[],
-                                int attrsonly, LDAPMessage **res);
-static int     ldap_getval_firststring(LDAP *ld, LDAPMessage *entry,
-                                        char *attr, char *retval,
-                                        unsigned long maxsize);
-static void    ldap_freeres(LDAPMessage *entry);
-static void    send_ldap_ou(char *ou, char *basedn, char *descstring);
-static void    send_ldap_browse(cupsd_printer_t *p);
-static void    ldap_dereg_printer(cupsd_printer_t *p);
-static void    ldap_dereg_ou(char *ou, char *basedn);
-#  ifdef HAVE_LDAP_REBIND_PROC
-#    if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
-static int     ldap_rebind_proc(LDAP *RebindLDAPHandle,
-                                 LDAP_CONST char *refsp,
-                                 ber_tag_t request,
-                                 ber_int_t msgid,
-                                 void *params);
-#    else
-static int     ldap_rebind_proc(LDAP *RebindLDAPHandle,
-                                 char **dnp,
-                                 char **passwdp,
-                                 int *authmethodp,
-                                 int freeit,
-                                 void *arg);
-#    endif /* defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000) */
-#  endif /* HAVE_LDAP_REBIND_PROC */
-#endif /* HAVE_LDAP */
-#ifdef HAVE_LIBSLP
-static void    send_slp_browse(cupsd_printer_t *p);
-#endif /* HAVE_LIBSLP */
-static void    update_cups_browse(void);
 static void    update_lpd(int onoff);
-static void    update_polling(void);
 static void    update_smb(int onoff);
 
 
@@ -166,7 +82,6 @@ static void  dnssdAddAlias(const void *key, const void *value,
 #  endif /* HAVE_COREFOUNDATION */
 static char    *dnssdBuildTxtRecord(int *txt_len, cupsd_printer_t *p,
                                     int for_lpd);
-static int     dnssdComparePrinters(cupsd_printer_t *a, cupsd_printer_t *b);
 static void    dnssdDeregisterPrinter(cupsd_printer_t *p);
 static char    *dnssdPackTxtRecord(int *txt_len, char *keyvalue[][2],
                                    int count);
@@ -180,59 +95,6 @@ static void dnssdStop(void);
 static void    dnssdUpdate(void);
 #endif /* HAVE_DNSSD */
 
-#ifdef HAVE_LDAP
-static const char * const ldap_attrs[] =/* CUPS LDAP attributes */
-               {
-                 "printerDescription",
-                 "printerLocation",
-                 "printerMakeAndModel",
-                 "printerType",
-                 "printerURI",
-                 NULL
-               };
-#endif /* HAVE_LDAP */
-
-#ifdef HAVE_LIBSLP
-/*
- * SLP definitions...
- */
-
-/*
- * SLP service name for CUPS...
- */
-
-#  define SLP_CUPS_SRVTYPE     "service:printer"
-#  define SLP_CUPS_SRVLEN      15
-
-
-/*
- * Printer service URL structure
- */
-
-typedef struct _slpsrvurl_s            /**** SLP URL list ****/
-{
-  struct _slpsrvurl_s  *next;          /* Next URL in list */
-  char                 url[HTTP_MAX_URI];
-                                       /* URL */
-} slpsrvurl_t;
-
-
-/*
- * Local functions...
- */
-
-static SLPBoolean      slp_attr_callback(SLPHandle hslp, const char *attrlist,
-                                         SLPError errcode, void *cookie);
-static void            slp_dereg_printer(cupsd_printer_t *p);
-static int             slp_get_attr(const char *attrlist, const char *tag,
-                                    char **valbuf);
-static void            slp_reg_callback(SLPHandle hslp, SLPError errcode,
-                                        void *cookie);
-static SLPBoolean      slp_url_callback(SLPHandle hslp, const char *srvurl,
-                                        unsigned short lifetime,
-                                        SLPError errcode, void *cookie);
-#endif /* HAVE_LIBSLP */
-
 
 /*
  * 'cupsdDeregisterPrinter()' - Stop sending broadcast information for a
@@ -254,5125 +116,1104 @@ cupsdDeregisterPrinter(
                  removeit);
 
   if (!Browsing || !p->shared ||
-      (p->type & (CUPS_PRINTER_REMOTE | CUPS_PRINTER_IMPLICIT |
-                  CUPS_PRINTER_SCANNER)))
+      (p->type & (CUPS_PRINTER_REMOTE | CUPS_PRINTER_SCANNER)))
     return;
 
  /*
   * Announce the deletion...
   */
 
-  if ((BrowseLocalProtocols & BROWSE_CUPS) && BrowseSocket >= 0)
-  {
-    cups_ptype_t savedtype = p->type;  /* Saved printer type */
-
-    p->type |= CUPS_PRINTER_DELETE;
+#ifdef HAVE_DNSSD
+  if (removeit && (BrowseLocalProtocols & BROWSE_DNSSD) && DNSSDRef)
+    dnssdDeregisterPrinter(p);
+#endif /* HAVE_DNSSD */
+}
 
-    send_cups_browse(p);
 
-    p->type = savedtype;
-  }
+/*
+ * 'cupsdRegisterPrinter()' - Start sending broadcast information for a
+ *                            printer or update the broadcast contents.
+ */
 
-#ifdef HAVE_LIBSLP
-  if (BrowseLocalProtocols & BROWSE_SLP)
-    slp_dereg_printer(p);
-#endif /* HAVE_LIBSLP */
+void
+cupsdRegisterPrinter(cupsd_printer_t *p)/* I - Printer */
+{
+  cupsdLogMessage(CUPSD_LOG_DEBUG, "cupsdRegisterPrinter(p=%p(%s))", p,
+                  p->name);
 
-#ifdef HAVE_LDAP
-  if (BrowseLocalProtocols & BROWSE_LDAP)
-    ldap_dereg_printer(p);
-#endif /* HAVE_LDAP */
+  if (!Browsing || !BrowseLocalProtocols ||
+      (p->type & (CUPS_PRINTER_REMOTE | CUPS_PRINTER_SCANNER)))
+    return;
 
 #ifdef HAVE_DNSSD
-  if (removeit && (BrowseLocalProtocols & BROWSE_DNSSD) && DNSSDRef)
-    dnssdDeregisterPrinter(p);
+  if ((BrowseLocalProtocols & BROWSE_DNSSD) && DNSSDRef)
+    dnssdRegisterPrinter(p);
 #endif /* HAVE_DNSSD */
 }
 
 
 /*
- * 'cupsdLoadRemoteCache()' - Load the remote printer cache.
+ * 'cupsdStartBrowsing()' - Start sending and receiving broadcast information.
  */
 
 void
-cupsdLoadRemoteCache(void)
+cupsdStartBrowsing(void)
 {
-  int                  i;              /* Looping var */
-  cups_file_t          *fp;            /* remote.cache file */
-  int                  linenum;        /* Current line number */
-  char                 line[4096],     /* Line from file */
-                       *value,         /* Pointer to value */
-                       *valueptr,      /* Pointer into value */
-                       scheme[32],     /* Scheme portion of URI */
-                       username[64],   /* Username portion of URI */
-                       host[HTTP_MAX_HOST],
-                                       /* Hostname portion of URI */
-                       resource[HTTP_MAX_URI];
-                                       /* Resource portion of URI */
-  int                  port;           /* Port number */
   cupsd_printer_t      *p;             /* Current printer */
-  time_t               now;            /* Current time */
-
-
- /*
-  * Don't load the cache if the remote protocols are disabled...
-  */
 
-  if (!Browsing)
-  {
-    cupsdLogMessage(CUPSD_LOG_DEBUG,
-                    "cupsdLoadRemoteCache: Not loading remote cache.");
-    return;
-  }
 
- /*
-  * Open the remote.cache file...
-  */
-
-  snprintf(line, sizeof(line), "%s/remote.cache", CacheDir);
-  if ((fp = cupsdOpenConfFile(line)) == NULL)
+  if (!Browsing || !BrowseLocalProtocols)
     return;
 
- /*
-  * Read printer configurations until we hit EOF...
-  */
+#ifdef HAVE_DNSSD
+  if (BrowseLocalProtocols & BROWSE_DNSSD)
+  {
+    DNSServiceErrorType error;         /* Error from service creation */
+    cupsd_listener_t   *lis;           /* Current listening socket */
 
-  linenum = 0;
-  p       = NULL;
-  now     = time(NULL);
 
-  while (cupsFileGetConf(fp, line, sizeof(line), &value, &linenum))
-  {
    /*
-    * Decode the directive...
+    * First create a "master" connection for all registrations...
     */
 
-    if (!_cups_strcasecmp(line, "<Printer") ||
-        !_cups_strcasecmp(line, "<DefaultPrinter"))
-    {
-     /*
-      * <Printer name> or <DefaultPrinter name>
-      */
-
-      if (p == NULL && value)
-      {
-       /*
-        * Add the printer and a base file type...
-       */
-
-        cupsdLogMessage(CUPSD_LOG_DEBUG,
-                       "cupsdLoadRemoteCache: Loading printer %s...", value);
-
-        if ((p = cupsdFindDest(value)) != NULL)
-       {
-         if (p->type & CUPS_PRINTER_CLASS)
-         {
-           cupsdLogMessage(CUPSD_LOG_WARN,
-                           "Cached remote printer \"%s\" conflicts with "
-                           "existing class!",
-                           value);
-           p = NULL;
-           continue;
-         }
-       }
-       else
-          p = cupsdAddPrinter(value);
-
-       p->accepting     = 1;
-       p->state         = IPP_PRINTER_IDLE;
-       p->type          |= CUPS_PRINTER_REMOTE | CUPS_PRINTER_DISCOVERED;
-       p->browse_time   = now;
-       p->browse_expire = now + BrowseTimeout;
-
-       /*
-        * Set the default printer as needed...
-       */
-
-        if (!_cups_strcasecmp(line, "<DefaultPrinter"))
-         DefaultPrinter = p;
-      }
-      else
-      {
-        cupsdLogMessage(CUPSD_LOG_ERROR,
-                       "Syntax error on line %d of remote.cache.", linenum);
-        break;
-      }
-    }
-    else if (!_cups_strcasecmp(line, "<Class") ||
-             !_cups_strcasecmp(line, "<DefaultClass"))
-    {
-     /*
-      * <Class name> or <DefaultClass name>
-      */
-
-      if (p == NULL && value)
-      {
-       /*
-        * Add the printer and a base file type...
-       */
-
-        cupsdLogMessage(CUPSD_LOG_DEBUG,
-                       "cupsdLoadRemoteCache: Loading class %s...", value);
-
-        if ((p = cupsdFindDest(value)) != NULL)
-         p->type = CUPS_PRINTER_CLASS;
-       else
-          p = cupsdAddClass(value);
-
-       p->accepting     = 1;
-       p->state         = IPP_PRINTER_IDLE;
-       p->type          |= CUPS_PRINTER_REMOTE | CUPS_PRINTER_DISCOVERED;
-       p->browse_time   = now;
-       p->browse_expire = now + BrowseTimeout;
-
-       /*
-        * Set the default printer as needed...
-       */
-
-        if (!_cups_strcasecmp(line, "<DefaultClass"))
-         DefaultPrinter = p;
-      }
-      else
-      {
-        cupsdLogMessage(CUPSD_LOG_ERROR,
-                       "Syntax error on line %d of remote.cache.", linenum);
-        break;
-      }
-    }
-    else if (!_cups_strcasecmp(line, "</Printer>") ||
-             !_cups_strcasecmp(line, "</Class>"))
-    {
-      if (p != NULL)
-      {
-       /*
-        * Close out the current printer...
-       */
-
-        cupsdSetPrinterAttrs(p);
-
-        p = NULL;
-      }
-      else
-        cupsdLogMessage(CUPSD_LOG_ERROR,
-                       "Syntax error on line %d of remote.cache.", linenum);
-    }
-    else if (!p)
+    if ((error = DNSServiceCreateConnection(&DNSSDRef))
+           != kDNSServiceErr_NoError)
     {
       cupsdLogMessage(CUPSD_LOG_ERROR,
-                      "Syntax error on line %d of remote.cache.", linenum);
-    }
-    else if (!_cups_strcasecmp(line, "UUID"))
-    {
-      if (value && !strncmp(value, "urn:uuid:", 9))
-        cupsdSetString(&(p->uuid), value);
-      else
-        cupsdLogMessage(CUPSD_LOG_ERROR,
-                       "Bad UUID on line %d of remote.cache.", linenum);
-    }
-    else if (!_cups_strcasecmp(line, "Info"))
-    {
-      if (value)
-       cupsdSetString(&p->info, value);
-    }
-    else if (!_cups_strcasecmp(line, "MakeModel"))
-    {
-      if (value)
-       cupsdSetString(&p->make_model, value);
-    }
-    else if (!_cups_strcasecmp(line, "Location"))
-    {
-      if (value)
-       cupsdSetString(&p->location, value);
-    }
-    else if (!_cups_strcasecmp(line, "DeviceURI"))
-    {
-      if (value)
-      {
-       httpSeparateURI(HTTP_URI_CODING_ALL, value, scheme, sizeof(scheme),
-                       username, sizeof(username), host, sizeof(host), &port,
-                       resource, sizeof(resource));
+                     "Unable to create master DNS-SD reference: %d", error);
 
-       cupsdSetString(&p->hostname, host);
-       cupsdSetString(&p->uri, value);
-       cupsdSetDeviceURI(p, value);
-      }
-      else
-       cupsdLogMessage(CUPSD_LOG_ERROR,
-                       "Syntax error on line %d of remote.cache.", linenum);
+      if (FatalErrors & CUPSD_FATAL_BROWSE)
+       cupsdEndProcess(getpid(), 0);
     }
-    else if (!_cups_strcasecmp(line, "Option") && value)
+    else
     {
      /*
-      * Option name value
+      * Add the master connection to the select list...
       */
 
-      for (valueptr = value; *valueptr && !isspace(*valueptr & 255); valueptr ++);
+      int fd = DNSServiceRefSockFD(DNSSDRef);
 
-      if (!*valueptr)
-        cupsdLogMessage(CUPSD_LOG_ERROR,
-                       "Syntax error on line %d of remote.cache.", linenum);
-      else
-      {
-        for (; *valueptr && isspace(*valueptr & 255); *valueptr++ = '\0');
+      fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
 
-        p->num_options = cupsAddOption(value, valueptr, p->num_options,
-                                      &(p->options));
-      }
-    }
-    else if (!_cups_strcasecmp(line, "Reason"))
-    {
-      if (value)
-      {
-        for (i = 0 ; i < p->num_reasons; i ++)
-         if (!strcmp(value, p->reasons[i]))
-           break;
-
-        if (i >= p->num_reasons &&
-           p->num_reasons < (int)(sizeof(p->reasons) / sizeof(p->reasons[0])))
-       {
-         p->reasons[p->num_reasons] = _cupsStrAlloc(value);
-         p->num_reasons ++;
-       }
-      }
-      else
-       cupsdLogMessage(CUPSD_LOG_ERROR,
-                       "Syntax error on line %d of remote.cache.", linenum);
-    }
-    else if (!_cups_strcasecmp(line, "State"))
-    {
-     /*
-      * Set the initial queue state...
-      */
+      cupsdAddSelect(fd, (cupsd_selfunc_t)dnssdUpdate, NULL, NULL);
 
-      if (value && !_cups_strcasecmp(value, "idle"))
-        p->state = IPP_PRINTER_IDLE;
-      else if (value && !_cups_strcasecmp(value, "stopped"))
-      {
-        p->state = IPP_PRINTER_STOPPED;
-       cupsdSetPrinterReasons(p, "+paused");
-      }
-      else
-       cupsdLogMessage(CUPSD_LOG_ERROR,
-                       "Syntax error on line %d of remote.cache.", linenum);
-    }
-    else if (!_cups_strcasecmp(line, "StateMessage"))
-    {
      /*
-      * Set the initial queue state message...
+      * Then get the port we use for registrations.  If we are not listening
+      * on any non-local ports, there is no sense sharing local printers via
+      * Bonjour...
       */
 
-      if (value)
-       strlcpy(p->state_message, value, sizeof(p->state_message));
-    }
-    else if (!_cups_strcasecmp(line, "Accepting"))
-    {
-     /*
-      * Set the initial accepting state...
-      */
+      DNSSDPort = 0;
 
-      if (value &&
-          (!_cups_strcasecmp(value, "yes") ||
-           !_cups_strcasecmp(value, "on") ||
-           !_cups_strcasecmp(value, "true")))
-        p->accepting = 1;
-      else if (value &&
-               (!_cups_strcasecmp(value, "no") ||
-               !_cups_strcasecmp(value, "off") ||
-               !_cups_strcasecmp(value, "false")))
-        p->accepting = 0;
-      else
-       cupsdLogMessage(CUPSD_LOG_ERROR,
-                       "Syntax error on line %d of remote.cache.", linenum);
-    }
-    else if (!_cups_strcasecmp(line, "Type"))
-    {
-      if (value)
-        p->type = atoi(value);
-      else
-       cupsdLogMessage(CUPSD_LOG_ERROR,
-                       "Syntax error on line %d of remote.cache.", linenum);
-    }
-    else if (!_cups_strcasecmp(line, "BrowseTime"))
-    {
-      if (value)
+      for (lis = (cupsd_listener_t *)cupsArrayFirst(Listeners);
+          lis;
+          lis = (cupsd_listener_t *)cupsArrayNext(Listeners))
       {
-        time_t t = atoi(value);
+       if (httpAddrLocalhost(&(lis->address)))
+         continue;
 
-       if (t > p->browse_expire)
-          p->browse_expire = t;
+        DNSSDPort = _httpAddrPort(&(lis->address));
+       break;
       }
-      else
-       cupsdLogMessage(CUPSD_LOG_ERROR,
-                       "Syntax error on line %d of remote.cache.", linenum);
-    }
-    else if (!_cups_strcasecmp(line, "JobSheets"))
-    {
-     /*
-      * Set the initial job sheets...
-      */
 
-      if (value)
-      {
-       for (valueptr = value; *valueptr && !isspace(*valueptr & 255); valueptr ++);
-
-       if (*valueptr)
-          *valueptr++ = '\0';
-
-       cupsdSetString(&p->job_sheets[0], value);
-
-       while (isspace(*valueptr & 255))
-          valueptr ++;
-
-       if (*valueptr)
-       {
-          for (value = valueptr; *valueptr && !isspace(*valueptr & 255); valueptr ++);
-
-         if (*valueptr)
-            *valueptr = '\0';
-
-         cupsdSetString(&p->job_sheets[1], value);
-       }
-      }
-      else
-       cupsdLogMessage(CUPSD_LOG_ERROR,
-                       "Syntax error on line %d of remote.cache.", linenum);
-    }
-    else if (!_cups_strcasecmp(line, "AllowUser"))
-    {
-      if (value)
-      {
-        p->deny_users = 0;
-        cupsdAddString(&(p->users), value);
-      }
-      else
-       cupsdLogMessage(CUPSD_LOG_ERROR,
-                       "Syntax error on line %d of remote.cache.", linenum);
-    }
-    else if (!_cups_strcasecmp(line, "DenyUser"))
-    {
-      if (value)
-      {
-        p->deny_users = 1;
-        cupsdAddString(&(p->users), value);
-      }
-      else
-       cupsdLogMessage(CUPSD_LOG_ERROR,
-                       "Syntax error on line %d of remote.cache.", linenum);
-    }
-    else
-    {
      /*
-      * Something else we don't understand...
+      * Set the computer name and register the web interface...
       */
 
-      cupsdLogMessage(CUPSD_LOG_ERROR,
-                      "Unknown configuration directive %s on line %d of remote.cache.",
-                     line, linenum);
+      cupsdUpdateDNSSDName();
     }
   }
+#endif /* HAVE_DNSSD */
+
+ /*
+  * Enable LPD and SMB printer sharing as needed through external programs...
+  */
+
+  if (BrowseLocalProtocols & BROWSE_LPD)
+    update_lpd(1);
 
-  cupsFileClose(fp);
+  if (BrowseLocalProtocols & BROWSE_SMB)
+    update_smb(1);
 
  /*
-  * Do auto-classing if needed...
+  * Register the individual printers
   */
 
-  process_implicit_classes();
+  for (p = (cupsd_printer_t *)cupsArrayFirst(Printers);
+       p;
+       p = (cupsd_printer_t *)cupsArrayNext(Printers))
+    if (!(p->type & (CUPS_PRINTER_REMOTE | CUPS_PRINTER_SCANNER)))
+      cupsdRegisterPrinter(p);
 }
 
 
 /*
- * 'cupsdRegisterPrinter()' - Start sending broadcast information for a
- *                            printer or update the broadcast contents.
+ * 'cupsdStopBrowsing()' - Stop sending and receiving broadcast information.
  */
 
 void
-cupsdRegisterPrinter(cupsd_printer_t *p)/* I - Printer */
+cupsdStopBrowsing(void)
 {
-  cupsdLogMessage(CUPSD_LOG_DEBUG, "cupsdRegisterPrinter(p=%p(%s))", p,
-                  p->name);
+  cupsd_printer_t      *p;             /* Current printer */
 
-  if (!Browsing || !BrowseLocalProtocols ||
-      (p->type & (CUPS_PRINTER_REMOTE | CUPS_PRINTER_IMPLICIT |
-                  CUPS_PRINTER_SCANNER)))
+
+  if (!Browsing || !BrowseLocalProtocols)
     return;
 
-#ifdef HAVE_LIBSLP
-/*  if (BrowseLocalProtocols & BROWSE_SLP)
-    slpRegisterPrinter(p); */
-#endif /* HAVE_LIBSLP */
+ /*
+  * De-register the individual printers
+  */
+
+  for (p = (cupsd_printer_t *)cupsArrayFirst(Printers);
+       p;
+       p = (cupsd_printer_t *)cupsArrayNext(Printers))
+    if (!(p->type & (CUPS_PRINTER_REMOTE | CUPS_PRINTER_SCANNER)))
+      cupsdDeregisterPrinter(p, 1);
+
+ /*
+  * Shut down browsing sockets...
+  */
 
 #ifdef HAVE_DNSSD
   if ((BrowseLocalProtocols & BROWSE_DNSSD) && DNSSDRef)
-    dnssdRegisterPrinter(p);
+    dnssdStop();
 #endif /* HAVE_DNSSD */
-}
-
-
-/*
- * 'cupsdRestartPolling()' - Restart polling servers as needed.
- */
 
-void
-cupsdRestartPolling(void)
-{
-  int                  i;              /* Looping var */
-  cupsd_dirsvc_poll_t  *pollp;         /* Current polling server */
+ /*
+  * Disable LPD and SMB printer sharing as needed through external programs...
+  */
 
+  if (BrowseLocalProtocols & BROWSE_LPD)
+    update_lpd(0);
 
-  for (i = 0, pollp = Polled; i < NumPolled; i ++, pollp ++)
-    if (pollp->pid)
-      kill(pollp->pid, SIGHUP);
+  if (BrowseLocalProtocols & BROWSE_SMB)
+    update_smb(0);
 }
 
 
+#ifdef HAVE_DNSSD
 /*
- * 'cupsdSaveRemoteCache()' - Save the remote printer cache.
+ * 'cupsdUpdateDNSSDName()' - Update the computer name we use for browsing...
  */
 
 void
-cupsdSaveRemoteCache(void)
+cupsdUpdateDNSSDName(void)
 {
-  int                  i;              /* Looping var */
-  cups_file_t          *fp;            /* remote.cache file */
-  char                 filename[1024], /* remote.cache filename */
-                       temp[1024],     /* Temporary string */
-                       value[2048],    /* Value string */
-                       *name;          /* Current user name */
-  cupsd_printer_t      *printer;       /* Current printer class */
-  time_t               curtime;        /* Current time */
-  struct tm            *curdate;       /* Current date */
-  cups_option_t                *option;        /* Current option */
+  DNSServiceErrorType error;           /* Error from service creation */
+  char         webif[1024];            /* Web interface share name */
+#  ifdef HAVE_SYSTEMCONFIGURATION
+  SCDynamicStoreRef sc;                        /* Context for dynamic store */
+  CFDictionaryRef btmm;                        /* Back-to-My-Mac domains */
+  CFStringEncoding nameEncoding;       /* Encoding of computer name */
+  CFStringRef  nameRef;                /* Host name CFString */
+  char         nameBuffer[1024];       /* C-string buffer */
+#  endif /* HAVE_SYSTEMCONFIGURATION */
 
 
  /*
-  * Create the remote.cache file...
-  */
-
-  snprintf(filename, sizeof(filename), "%s/remote.cache", CacheDir);
+  * Only share the web interface and printers when non-local listening is
+  * enabled...
+  */
 
-  if ((fp = cupsdCreateConfFile(filename, ConfigFilePerm)) == NULL)
+  if (!DNSSDPort)
     return;
 
-  cupsdLogMessage(CUPSD_LOG_DEBUG, "Saving remote.cache...");
-
  /*
-  * Write a small header to the file...
+  * Get the computer name as a c-string...
   */
 
-  curtime = time(NULL);
-  curdate = localtime(&curtime);
-  strftime(temp, sizeof(temp) - 1, "%Y-%m-%d %H:%M", curdate);
-
-  cupsFilePuts(fp, "# Remote cache file for " CUPS_SVERSION "\n");
-  cupsFilePrintf(fp, "# Written by cupsd on %s\n", temp);
-
- /*
-  * Write each local printer known to the system...
-  */
+#  ifdef HAVE_SYSTEMCONFIGURATION
+  sc = SCDynamicStoreCreate(kCFAllocatorDefault, CFSTR("cupsd"), NULL, NULL);
 
-  for (printer = (cupsd_printer_t *)cupsArrayFirst(Printers);
-       printer;
-       printer = (cupsd_printer_t *)cupsArrayNext(Printers))
+  if (sc)
   {
    /*
-    * Skip local destinations...
-    */
-
-    if (!(printer->type & CUPS_PRINTER_DISCOVERED))
-      continue;
-
-   /*
-    * Write printers as needed...
+    * Get the computer name from the dynamic store...
     */
 
-    if (printer == DefaultPrinter)
-      cupsFilePuts(fp, "<Default");
-    else
-      cupsFilePutChar(fp, '<');
-
-    if (printer->type & CUPS_PRINTER_CLASS)
-      cupsFilePrintf(fp, "Class %s>\n", printer->name);
-    else
-      cupsFilePrintf(fp, "Printer %s>\n", printer->name);
-
-    cupsFilePrintf(fp, "BrowseTime %d\n", (int)printer->browse_expire);
-
-    cupsFilePrintf(fp, "UUID %s\n", printer->uuid);
-
-    if (printer->info)
-      cupsFilePutConf(fp, "Info", printer->info);
-
-    if (printer->location)
-      cupsFilePutConf(fp, "Location", printer->location);
-
-    if (printer->make_model)
-      cupsFilePutConf(fp, "MakeModel", printer->make_model);
-
-    cupsFilePutConf(fp, "DeviceURI", printer->device_uri);
-
-    if (printer->state == IPP_PRINTER_STOPPED)
-      cupsFilePuts(fp, "State Stopped\n");
-    else
-      cupsFilePuts(fp, "State Idle\n");
-
-    for (i = 0; i < printer->num_reasons; i ++)
-      cupsFilePutConf(fp, "Reason", printer->reasons[i]);
-
-    cupsFilePrintf(fp, "Type %d\n", printer->type);
-
-    if (printer->accepting)
-      cupsFilePuts(fp, "Accepting Yes\n");
-    else
-      cupsFilePuts(fp, "Accepting No\n");
-
-    snprintf(value, sizeof(value), "%s %s", printer->job_sheets[0],
-             printer->job_sheets[1]);
-    cupsFilePutConf(fp, "JobSheets", value);
-
-    for (name = (char *)cupsArrayFirst(printer->users);
-        name;
-        name = (char *)cupsArrayNext(printer->users))
-      cupsFilePutConf(fp, printer->deny_users ? "DenyUser" : "AllowUser", name);
+    cupsdClearString(&DNSSDComputerName);
 
-    for (i = printer->num_options, option = printer->options;
-         i > 0;
-        i --, option ++)
+    if ((nameRef = SCDynamicStoreCopyComputerName(sc, &nameEncoding)) != NULL)
     {
-      snprintf(value, sizeof(value), "%s %s", option->name, option->value);
-      cupsFilePutConf(fp, "Option", value);
-    }
-
-    if (printer->type & CUPS_PRINTER_CLASS)
-      cupsFilePuts(fp, "</Class>\n");
-    else
-      cupsFilePuts(fp, "</Printer>\n");
-  }
-
-  cupsdCloseCreatedConfFile(fp, filename);
-}
-
-
-/*
- * 'cupsdSendBrowseList()' - Send new browsing information as necessary.
- */
-
-void
-cupsdSendBrowseList(void)
-{
-  int                  count;          /* Number of dests to update */
-  cupsd_printer_t      *p;             /* Current printer */
-  time_t               ut,             /* Minimum update time */
-                       to;             /* Timeout time */
-
-
-  if (!Browsing || !Printers)
-    return;
-
- /*
-  * Compute the update and timeout times...
-  */
-
-  to = time(NULL);
-  ut = to - BrowseInterval;
+      if (CFStringGetCString(nameRef, nameBuffer, sizeof(nameBuffer),
+                            kCFStringEncodingUTF8))
+      {
+        cupsdLogMessage(CUPSD_LOG_DEBUG,
+                       "Dynamic store computer name is \"%s\".", nameBuffer);
+       cupsdSetString(&DNSSDComputerName, nameBuffer);
+      }
 
- /*
-  * Figure out how many printers need an update...
-  */
+      CFRelease(nameRef);
+    }
 
-  if (BrowseInterval > 0 && BrowseLocalProtocols)
-  {
-    int        max_count;                      /* Maximum number to update */
+    if (!DNSSDComputerName)
+    {
+     /*
+      * Use the ServerName instead...
+      */
 
+      cupsdLogMessage(CUPSD_LOG_DEBUG,
+                      "Using ServerName \"%s\" as computer name.", ServerName);
+      cupsdSetString(&DNSSDComputerName, ServerName);
+    }
 
    /*
-    * Throttle the number of printers we'll be updating this time
-    * around based on the number of queues that need updating and
-    * the maximum number of queues to update each second...
+    * Get the local hostname from the dynamic store...
     */
 
-    max_count = 2 * cupsArrayCount(Printers) / BrowseInterval + 1;
-
-    for (count = 0, p = (cupsd_printer_t *)cupsArrayFirst(Printers);
-         count < max_count && p != NULL;
-        p = (cupsd_printer_t *)cupsArrayNext(Printers))
-      if (!(p->type & (CUPS_PRINTER_REMOTE | CUPS_PRINTER_IMPLICIT |
-                       CUPS_PRINTER_SCANNER)) &&
-          p->shared && p->browse_time < ut)
-        count ++;
+    cupsdClearString(&DNSSDHostName);
 
-   /*
-    * Loop through all of the printers and send local updates as needed...
-    */
+    if ((nameRef = SCDynamicStoreCopyLocalHostName(sc)) != NULL)
+    {
+      if (CFStringGetCString(nameRef, nameBuffer, sizeof(nameBuffer),
+                            kCFStringEncodingUTF8))
+      {
+        cupsdLogMessage(CUPSD_LOG_DEBUG,
+                       "Dynamic store host name is \"%s\".", nameBuffer);
+       cupsdSetString(&DNSSDHostName, nameBuffer);
+      }
 
-    if (BrowseNext)
-      p = (cupsd_printer_t *)cupsArrayFind(Printers, BrowseNext);
-    else
-      p = (cupsd_printer_t *)cupsArrayFirst(Printers);
+      CFRelease(nameRef);
+    }
 
-    for (;
-         count > 0;
-        p = (cupsd_printer_t *)cupsArrayNext(Printers))
+    if (!DNSSDHostName)
     {
      /*
-      * Check for wraparound...
+      * Use the ServerName instead...
       */
 
-      if (!p)
-        p = (cupsd_printer_t *)cupsArrayFirst(Printers);
-
-      if (!p)
-        break;
-      else if ((p->type & (CUPS_PRINTER_REMOTE | CUPS_PRINTER_IMPLICIT |
-                           CUPS_PRINTER_SCANNER)) ||
-               !p->shared)
-        continue;
-      else if (p->browse_time < ut)
-      {
-       /*
-       * Need to send an update...
-       */
-
-       count --;
-
-       p->browse_time = time(NULL);
-
-       if ((BrowseLocalProtocols & BROWSE_CUPS) && BrowseSocket >= 0)
-          send_cups_browse(p);
-
-#ifdef HAVE_LIBSLP
-       if (BrowseLocalProtocols & BROWSE_SLP)
-          send_slp_browse(p);
-#endif /* HAVE_LIBSLP */
-
-#ifdef HAVE_LDAP
-       if (BrowseLocalProtocols & BROWSE_LDAP)
-          send_ldap_browse(p);
-#endif /* HAVE_LDAP */
-      }
+      cupsdLogMessage(CUPSD_LOG_DEBUG,
+                      "Using ServerName \"%s\" as host name.", ServerName);
+      cupsdSetString(&DNSSDHostName, ServerName);
     }
 
    /*
-    * Save where we left off so that all printers get updated...
+    * Get any Back-to-My-Mac domains and add them as aliases...
     */
 
-    BrowseNext = p;
-  }
-
- /*
-  * Loop through all of the printers and timeout old printers as needed...
-  */
-
-  for (p = (cupsd_printer_t *)cupsArrayFirst(Printers);
-       p;
-       p = (cupsd_printer_t *)cupsArrayNext(Printers))
-  {
-   /*
-    * If this is a remote queue, see if it needs to be timed out...
-    */
+    cupsdFreeAliases(DNSSDAlias);
+    DNSSDAlias = NULL;
 
-    if ((p->type & CUPS_PRINTER_DISCOVERED) &&
-        !(p->type & CUPS_PRINTER_IMPLICIT) &&
-       p->browse_expire < to)
+    btmm = SCDynamicStoreCopyValue(sc, CFSTR("Setup:/Network/BackToMyMac"));
+    if (btmm && CFGetTypeID(btmm) == CFDictionaryGetTypeID())
     {
-      cupsdAddEvent(CUPSD_EVENT_PRINTER_DELETED, p, NULL,
-                   "%s \'%s\' deleted by directory services (timeout).",
-                   (p->type & CUPS_PRINTER_CLASS) ? "Class" : "Printer",
-                   p->name);
-
-      cupsdLogMessage(CUPSD_LOG_DEBUG,
-                     "Remote destination \"%s\" has timed out; "
-                     "deleting it...",
-                     p->name);
-
-      cupsArraySave(Printers);
-      cupsdDeletePrinter(p, 1);
-      cupsArrayRestore(Printers);
-      cupsdMarkDirty(CUPSD_DIRTY_PRINTCAP | CUPSD_DIRTY_REMOTE);
+      cupsdLogMessage(CUPSD_LOG_DEBUG, "%d Back to My Mac aliases to add.",
+                     (int)CFDictionaryGetCount(btmm));
+      CFDictionaryApplyFunction(btmm, dnssdAddAlias, NULL);
     }
-  }
-}
-
-
-#ifdef HAVE_LDAP_REBIND_PROC
-#  if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
-/*
- * 'ldap_rebind_proc()' - Callback function for LDAP rebind
- */
-
-static int                             /* O - Result code */
-ldap_rebind_proc(
-    LDAP            *RebindLDAPHandle, /* I - LDAP handle */
-    LDAP_CONST char *refsp,            /* I - ??? */
-    ber_tag_t       request,           /* I - ??? */
-    ber_int_t       msgid,             /* I - ??? */
-    void            *params)           /* I - ??? */
-{
-  int          rc;                     /* Result code */
-#    if LDAP_API_VERSION > 3000
-  struct berval        bval;                   /* Bind value */
-#    endif /* LDAP_API_VERSION > 3000 */
+    else if (btmm)
+      cupsdLogMessage(CUPSD_LOG_ERROR,
+                     "Bad Back to My Mac data in dynamic store!");
+    else
+      cupsdLogMessage(CUPSD_LOG_DEBUG, "No Back to My Mac aliases to add.");
 
+    if (btmm)
+      CFRelease(btmm);
 
-  (void)request;
-  (void)msgid;
-  (void)params;
+    CFRelease(sc);
+  }
+  else
+#  endif /* HAVE_SYSTEMCONFIGURATION */
+  {
+    cupsdSetString(&DNSSDComputerName, ServerName);
+    cupsdSetString(&DNSSDHostName, ServerName);
+  }
 
  /*
-  * Bind to new LDAP server...
+  * Then (re)register the web interface if enabled...
   */
 
-  cupsdLogMessage(CUPSD_LOG_DEBUG2, "ldap_rebind_proc: Rebind to %s", refsp);
-
-#    if LDAP_API_VERSION > 3000
-  bval.bv_val = BrowseLDAPPassword;
-  bval.bv_len = (BrowseLDAPPassword == NULL) ? 0 : strlen(BrowseLDAPPassword);
+  if (BrowseWebIF)
+  {
+    if (DNSSDComputerName)
+      snprintf(webif, sizeof(webif), "CUPS @ %s", DNSSDComputerName);
+    else
+      strlcpy(webif, "CUPS Web Interface", sizeof(webif));
 
-  rc = ldap_sasl_bind_s(RebindLDAPHandle, BrowseLDAPBindDN, LDAP_SASL_SIMPLE,
-                        &bval, NULL, NULL, NULL);
-#    else
-  rc = ldap_bind_s(RebindLDAPHandle, BrowseLDAPBindDN, BrowseLDAPPassword,
-                   LDAP_AUTH_SIMPLE);
-#    endif /* LDAP_API_VERSION > 3000 */
+    if (WebIFRef)
+      DNSServiceRefDeallocate(WebIFRef);
 
-  return (rc);
+    WebIFRef = DNSSDRef;
+    if ((error = DNSServiceRegister(&WebIFRef,
+                                   kDNSServiceFlagsShareConnection,
+                                   0, webif, "_http._tcp", NULL,
+                                   NULL, htons(DNSSDPort), 7,
+                                   "\006path=/", dnssdRegisterCallback,
+                                   NULL)) != kDNSServiceErr_NoError)
+      cupsdLogMessage(CUPSD_LOG_ERROR,
+                     "DNS-SD web interface registration failed: %d", error);
+  }
 }
+#endif /* HAVE_DNSSD */
 
 
-#  else /* defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000) */
+#ifdef HAVE_DNSSD
+#  ifdef HAVE_COREFOUNDATION
 /*
- * 'ldap_rebind_proc()' - Callback function for LDAP rebind
+ * 'dnssdAddAlias()' - Add a DNS-SD alias name.
  */
 
-static int                             /* O - Result code */
-ldap_rebind_proc(
-    LDAP *RebindLDAPHandle,            /* I - LDAP handle */
-    char **dnp,                                /* I - ??? */
-    char **passwdp,                    /* I - ??? */
-    int  *authmethodp,                 /* I - ??? */
-    int  freeit,                       /* I - ??? */
-    void *arg)                         /* I - ??? */
+static void
+dnssdAddAlias(const void *key,         /* I - Key */
+              const void *value,       /* I - Value (domain) */
+             void       *context)      /* I - Unused */
 {
-  switch (freeit)
-  {
-    case 1:
-       /*
-        * Free current values...
-        */
-
-        cupsdLogMessage(CUPSD_LOG_DEBUG2, "ldap_rebind_proc: Free values...");
-
-        if (dnp && *dnp)
-          free(*dnp);
-
-        if (passwdp && *passwdp)
-          free(*passwdp);
-        break;
-
-    case 0:
-       /*
-        * Return credentials for LDAP referal...
-        */
+  char valueStr[1024],                 /* Domain string */
+       hostname[1024];                 /* Complete hostname */
 
-        cupsdLogMessage(CUPSD_LOG_DEBUG2,
-                        "ldap_rebind_proc: Return necessary values...");
 
-        *dnp         = strdup(BrowseLDAPBindDN);
-        *passwdp     = strdup(BrowseLDAPPassword);
-        *authmethodp = LDAP_AUTH_SIMPLE;
-        break;
+  (void)key;
+  (void)context;
 
-    default:
-       /*
-        * Should never happen...
-        */
+  if (CFGetTypeID((CFStringRef)value) == CFStringGetTypeID() &&
+      CFStringGetCString((CFStringRef)value, valueStr, sizeof(valueStr),
+                         kCFStringEncodingUTF8))
+  {
+    snprintf(hostname, sizeof(hostname), "%s.%s", DNSSDHostName, valueStr);
+    if (!DNSSDAlias)
+      DNSSDAlias = cupsArrayNew(NULL, NULL);
 
-        cupsdLogMessage(CUPSD_LOG_ERROR,
-                        "LDAP rebind has been called with wrong freeit value!");
-        break;
+    cupsdAddAlias(DNSSDAlias, hostname);
+    cupsdLogMessage(CUPSD_LOG_DEBUG, "Added Back to My Mac ServerAlias %s",
+                   hostname);
   }
-
-  return (LDAP_SUCCESS);
+  else
+    cupsdLogMessage(CUPSD_LOG_ERROR,
+                    "Bad Back to My Mac domain in dynamic store!");
 }
-#  endif /* defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000) */
-#endif /* HAVE_LDAP_REBIND_PROC */
+#  endif /* HAVE_COREFOUNDATION */
 
 
-#ifdef HAVE_LDAP
 /*
- * 'ldap_connect()' - Start new LDAP connection
+ * 'dnssdBuildTxtRecord()' - Build a TXT record from printer info.
  */
 
-static LDAP *                          /* O - LDAP handle */
-ldap_connect(void)
-{
-  int          rc;                     /* LDAP API status */
-  int          version = 3;            /* LDAP version */
-  struct berval        bv = {0, ""};           /* SASL bind value */
-  LDAP         *TempBrowseLDAPHandle=NULL;
-                                       /* Temporary LDAP Handle */
-#  if defined(HAVE_LDAP_SSL) && defined (HAVE_MOZILLA_LDAP)
-  int          ldap_ssl = 0;           /* LDAP SSL indicator */
-  int          ssl_err = 0;            /* LDAP SSL error value */
-#  endif /* defined(HAVE_LDAP_SSL) && defined (HAVE_MOZILLA_LDAP) */
-
-
-#  ifdef HAVE_OPENLDAP
-#    ifdef HAVE_LDAP_SSL
- /*
-  * Set the certificate file to use for encrypted LDAP sessions...
-  */
-
-  if (BrowseLDAPCACertFile)
-  {
-    cupsdLogMessage(CUPSD_LOG_DEBUG,
-                   "ldap_connect: Setting CA certificate file \"%s\"",
-                    BrowseLDAPCACertFile);
-
-    if ((rc = ldap_set_option(NULL, LDAP_OPT_X_TLS_CACERTFILE,
-                             (void *)BrowseLDAPCACertFile)) != LDAP_SUCCESS)
-      cupsdLogMessage(CUPSD_LOG_ERROR,
-                      "Unable to set CA certificate file for LDAP "
-                      "connections: %d - %s", rc, ldap_err2string(rc));
-  }
-#    endif /* HAVE_LDAP_SSL */
-
- /*
-  * Initialize OPENLDAP connection...
-  * LDAP stuff currently only supports ldapi EXTERNAL SASL binds...
-  */
-
-  if (!BrowseLDAPServer || !_cups_strcasecmp(BrowseLDAPServer, "localhost"))
-    rc = ldap_initialize(&TempBrowseLDAPHandle, "ldapi:///");
-  else
-    rc = ldap_initialize(&TempBrowseLDAPHandle, BrowseLDAPServer);
-
-#  else /* HAVE_OPENLDAP */
-
-  int          ldap_port = 0;                  /* LDAP port */
-  char         ldap_protocol[11],              /* LDAP protocol */
-               ldap_host[255];                 /* LDAP host */
-
- /*
-  * Split LDAP URI into its components...
-  */
-
-  if (!BrowseLDAPServer)
-  {
-    cupsdLogMessage(CUPSD_LOG_ERROR, "BrowseLDAPServer not configured!");
-    cupsdLogMessage(CUPSD_LOG_ERROR, "Disabling LDAP browsing!");
-    BrowseLocalProtocols  &= ~BROWSE_LDAP;
-    BrowseRemoteProtocols &= ~BROWSE_LDAP;
-    return (NULL);
-  }
-
-  sscanf(BrowseLDAPServer, "%10[^:]://%254[^:/]:%d", ldap_protocol, ldap_host,
-         &ldap_port);
-
-  if (!strcmp(ldap_protocol, "ldap"))
-    ldap_ssl = 0;
-  else if (!strcmp(ldap_protocol, "ldaps"))
-    ldap_ssl = 1;
-  else
-  {
-    cupsdLogMessage(CUPSD_LOG_ERROR, "Unrecognized LDAP protocol (%s)!",
-                    ldap_protocol);
-    cupsdLogMessage(CUPSD_LOG_ERROR, "Disabling LDAP browsing!");
-    BrowseLocalProtocols &= ~BROWSE_LDAP;
-    BrowseRemoteProtocols &= ~BROWSE_LDAP;
-    return (NULL);
-  }
-
-  if (ldap_port == 0)
-  {
-    if (ldap_ssl)
-      ldap_port = LDAPS_PORT;
-    else
-      ldap_port = LDAP_PORT;
-  }
-
-  cupsdLogMessage(CUPSD_LOG_DEBUG, "ldap_connect: PROT:%s HOST:%s PORT:%d",
-                  ldap_protocol, ldap_host, ldap_port);
-
- /*
-  * Initialize LDAP connection...
-  */
-
-  if (!ldap_ssl)
-  {
-    if ((TempBrowseLDAPHandle = ldap_init(ldap_host, ldap_port)) == NULL)
-      rc = LDAP_OPERATIONS_ERROR;
-    else
-      rc = LDAP_SUCCESS;
-
-#    ifdef HAVE_LDAP_SSL
-  }
-  else
-  {
-   /*
-    * Initialize SSL LDAP connection...
-    */
-
-    if (BrowseLDAPCACertFile)
-    {
-      rc = ldapssl_client_init(BrowseLDAPCACertFile, (void *)NULL);
-      if (rc != LDAP_SUCCESS)
-      {
-        cupsdLogMessage(CUPSD_LOG_ERROR,
-                        "Failed to initialize LDAP SSL client!");
-        rc = LDAP_OPERATIONS_ERROR;
-      }
-      else
-      {
-        if ((TempBrowseLDAPHandle = ldapssl_init(ldap_host, ldap_port,
-                                                 1)) == NULL)
-          rc = LDAP_OPERATIONS_ERROR;
-        else
-          rc = LDAP_SUCCESS;
-      }
-    }
-    else
-    {
-      cupsdLogMessage(CUPSD_LOG_ERROR,
-                      "LDAP SSL certificate file/database not configured!");
-      rc = LDAP_OPERATIONS_ERROR;
-    }
-
-#    else /* HAVE_LDAP_SSL */
-
-   /*
-    * Return error, because client libraries doesn't support SSL
-    */
-
-    cupsdLogMessage(CUPSD_LOG_ERROR,
-                    "LDAP client libraries do not support SSL");
-    rc = LDAP_OPERATIONS_ERROR;
-
-#    endif /* HAVE_LDAP_SSL */
-  }
-#  endif /* HAVE_OPENLDAP */
-
- /*
-  * Check return code from LDAP initialize...
-  */
-
-  if (rc != LDAP_SUCCESS)
-  {
-    cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to initialize LDAP!");
-
-    if (rc == LDAP_SERVER_DOWN || rc == LDAP_CONNECT_ERROR)
-      cupsdLogMessage(CUPSD_LOG_ERROR, "Temporarily disabling LDAP browsing...");
-    else
-    {
-      cupsdLogMessage(CUPSD_LOG_ERROR, "Disabling LDAP browsing!");
-
-      BrowseLocalProtocols  &= ~BROWSE_LDAP;
-      BrowseRemoteProtocols &= ~BROWSE_LDAP;
-    }
-
-    ldap_disconnect(TempBrowseLDAPHandle);
-
-    return (NULL);
-  }
-
- /*
-  * Upgrade LDAP version...
-  */
-
-  if (ldap_set_option(TempBrowseLDAPHandle, LDAP_OPT_PROTOCOL_VERSION,
-                           (const void *)&version) != LDAP_SUCCESS)
-  {
-    cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to set LDAP protocol version %d!",
-                   version);
-    cupsdLogMessage(CUPSD_LOG_ERROR, "Disabling LDAP browsing!");
-
-    BrowseLocalProtocols  &= ~BROWSE_LDAP;
-    BrowseRemoteProtocols &= ~BROWSE_LDAP;
-    ldap_disconnect(TempBrowseLDAPHandle);
-
-    return (NULL);
-  }
-
- /*
-  * Register LDAP rebind procedure...
-  */
-
-#  ifdef HAVE_LDAP_REBIND_PROC
-#    if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
-
-  rc = ldap_set_rebind_proc(TempBrowseLDAPHandle, &ldap_rebind_proc,
-                            (void *)NULL);
-  if (rc != LDAP_SUCCESS)
-    cupsdLogMessage(CUPSD_LOG_ERROR,
-                    "Setting LDAP rebind function failed with status %d: %s",
-                    rc, ldap_err2string(rc));
-
-#    else
-
-  ldap_set_rebind_proc(TempBrowseLDAPHandle, &ldap_rebind_proc, (void *)NULL);
-
-#    endif /* defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000) */
-#  endif /* HAVE_LDAP_REBIND_PROC */
-
- /*
-  * Start LDAP bind...
-  */
-
-#  if LDAP_API_VERSION > 3000
-  struct berval bval;
-  bval.bv_val = BrowseLDAPPassword;
-  bval.bv_len = (BrowseLDAPPassword == NULL) ? 0 : strlen(BrowseLDAPPassword);
-
-  if (!BrowseLDAPServer || !_cups_strcasecmp(BrowseLDAPServer, "localhost"))
-    rc = ldap_sasl_bind_s(TempBrowseLDAPHandle, NULL, "EXTERNAL", &bv, NULL,
-                          NULL, NULL);
-  else
-    rc = ldap_sasl_bind_s(TempBrowseLDAPHandle, BrowseLDAPBindDN, LDAP_SASL_SIMPLE, &bval, NULL, NULL, NULL);
-
-#  else
-    rc = ldap_bind_s(TempBrowseLDAPHandle, BrowseLDAPBindDN,
-                     BrowseLDAPPassword, LDAP_AUTH_SIMPLE);
-#  endif /* LDAP_API_VERSION > 3000 */
-
-  if (rc != LDAP_SUCCESS)
-  {
-    cupsdLogMessage(CUPSD_LOG_ERROR, "LDAP bind failed with error %d: %s",
-                    rc, ldap_err2string(rc));
-
-#  if defined(HAVE_LDAP_SSL) && defined (HAVE_MOZILLA_LDAP)
-    if (ldap_ssl && (rc == LDAP_SERVER_DOWN || rc == LDAP_CONNECT_ERROR))
-    {
-      ssl_err = PORT_GetError();
-      if (ssl_err != 0)
-        cupsdLogMessage(CUPSD_LOG_ERROR, "LDAP SSL error %d: %s", ssl_err,
-                        ldapssl_err2string(ssl_err));
-    }
-#  endif /* defined(HAVE_LDAP_SSL) && defined (HAVE_MOZILLA_LDAP) */
-
-    ldap_disconnect(TempBrowseLDAPHandle);
-
-    return (NULL);
-  }
-
-  cupsdLogMessage(CUPSD_LOG_INFO, "LDAP connection established");
-
-  return (TempBrowseLDAPHandle);
-}
-
-
-/*
- * 'ldap_reconnect()' - Reconnect to LDAP Server
- */
-
-static LDAP *                          /* O - New LDAP handle */
-ldap_reconnect(void)
-{
-  LDAP *TempBrowseLDAPHandle = NULL;   /* Temp Handle to LDAP server */
-
-
- /*
-  * Get a new LDAP Handle and replace the global Handle
-  * if the new connection was successful.
-  */
-
-  cupsdLogMessage(CUPSD_LOG_INFO, "Try LDAP reconnect...");
-
-  TempBrowseLDAPHandle = ldap_connect();
-
-  if (TempBrowseLDAPHandle != NULL)
-  {
-    if (BrowseLDAPHandle != NULL)
-      ldap_disconnect(BrowseLDAPHandle);
-
-    BrowseLDAPHandle = TempBrowseLDAPHandle;
-  }
-
-  return (BrowseLDAPHandle);
-}
-
-
-/*
- * 'ldap_disconnect()' - Disconnect from LDAP Server
- */
-
-static void
-ldap_disconnect(LDAP *ld)              /* I - LDAP handle */
-{
-  int  rc;                             /* Return code */
-
-
- /*
-  * Close LDAP handle...
-  */
-
-#  if defined(HAVE_OPENLDAP) && LDAP_API_VERSION > 3000
-  rc = ldap_unbind_ext_s(ld, NULL, NULL);
-#  else
-  rc = ldap_unbind_s(ld);
-#  endif /* defined(HAVE_OPENLDAP) && LDAP_API_VERSION > 3000 */
-
-  if (rc != LDAP_SUCCESS)
-    cupsdLogMessage(CUPSD_LOG_ERROR,
-                    "Unbind from LDAP server failed with status %d: %s",
-                    rc, ldap_err2string(rc));
-}
-#endif /* HAVE_LDAP */
-
-
-/*
- * 'cupsdStartBrowsing()' - Start sending and receiving broadcast information.
- */
-
-void
-cupsdStartBrowsing(void)
-{
-  int                  val;            /* Socket option value */
-  struct sockaddr_in   addr;           /* Broadcast address */
-  cupsd_printer_t      *p;             /* Current printer */
-
-
-  BrowseNext = NULL;
-
-  if (!Browsing || !(BrowseLocalProtocols | BrowseRemoteProtocols))
-    return;
-
-  if ((BrowseLocalProtocols | BrowseRemoteProtocols) & BROWSE_CUPS)
-  {
-    if (BrowseSocket < 0)
-    {
-     /*
-      * Create the broadcast socket...
-      */
-
-      if ((BrowseSocket = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
-      {
-       cupsdLogMessage(CUPSD_LOG_ERROR,
-                       "Unable to create broadcast socket - %s.",
-                       strerror(errno));
-       BrowseLocalProtocols &= ~BROWSE_CUPS;
-       BrowseRemoteProtocols &= ~BROWSE_CUPS;
-
-       if (FatalErrors & CUPSD_FATAL_BROWSE)
-         cupsdEndProcess(getpid(), 0);
-      }
-    }
-
-    if (BrowseSocket >= 0)
-    {
-     /*
-      * Bind the socket to browse port...
-      */
-
-      memset(&addr, 0, sizeof(addr));
-      addr.sin_addr.s_addr = htonl(INADDR_ANY);
-      addr.sin_family      = AF_INET;
-      addr.sin_port        = htons(BrowsePort);
-
-      if (bind(BrowseSocket, (struct sockaddr *)&addr, sizeof(addr)))
-      {
-       cupsdLogMessage(CUPSD_LOG_ERROR,
-                       "Unable to bind broadcast socket - %s.",
-                       strerror(errno));
-
-#ifdef WIN32
-       closesocket(BrowseSocket);
-#else
-       close(BrowseSocket);
-#endif /* WIN32 */
-
-       BrowseSocket = -1;
-       BrowseLocalProtocols &= ~BROWSE_CUPS;
-       BrowseRemoteProtocols &= ~BROWSE_CUPS;
-
-       if (FatalErrors & CUPSD_FATAL_BROWSE)
-         cupsdEndProcess(getpid(), 0);
-      }
-    }
-
-    if (BrowseSocket >= 0)
-    {
-     /*
-      * Set the "broadcast" flag...
-      */
-
-      val = 1;
-      if (setsockopt(BrowseSocket, SOL_SOCKET, SO_BROADCAST, &val, sizeof(val)))
-      {
-       cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to set broadcast mode - %s.",
-                       strerror(errno));
-
-#ifdef WIN32
-       closesocket(BrowseSocket);
-#else
-       close(BrowseSocket);
-#endif /* WIN32 */
-
-       BrowseSocket = -1;
-       BrowseLocalProtocols &= ~BROWSE_CUPS;
-       BrowseRemoteProtocols &= ~BROWSE_CUPS;
-
-       if (FatalErrors & CUPSD_FATAL_BROWSE)
-         cupsdEndProcess(getpid(), 0);
-      }
-    }
-
-    if (BrowseSocket >= 0)
-    {
-     /*
-      * Close the socket on exec...
-      */
-
-      fcntl(BrowseSocket, F_SETFD, fcntl(BrowseSocket, F_GETFD) | FD_CLOEXEC);
-
-     /*
-      * Finally, add the socket to the input selection set as needed...
-      */
-
-      if (BrowseRemoteProtocols & BROWSE_CUPS)
-      {
-       /*
-       * We only listen if we want remote printers...
-       */
-
-       cupsdAddSelect(BrowseSocket, (cupsd_selfunc_t)update_cups_browse,
-                      NULL, NULL);
-      }
-    }
-  }
-  else
-    BrowseSocket = -1;
-
-#ifdef HAVE_DNSSD
-  if ((BrowseLocalProtocols | BrowseRemoteProtocols) & BROWSE_DNSSD)
-  {
-    DNSServiceErrorType error;         /* Error from service creation */
-    cupsd_listener_t   *lis;           /* Current listening socket */
-
-
-   /*
-    * First create a "master" connection for all registrations...
-    */
-
-    if ((error = DNSServiceCreateConnection(&DNSSDRef))
-           != kDNSServiceErr_NoError)
-    {
-      cupsdLogMessage(CUPSD_LOG_ERROR,
-                     "Unable to create master DNS-SD reference: %d", error);
-
-      if (FatalErrors & CUPSD_FATAL_BROWSE)
-       cupsdEndProcess(getpid(), 0);
-    }
-    else
-    {
-     /*
-      * Add the master connection to the select list...
-      */
-
-      int fd = DNSServiceRefSockFD(DNSSDRef);
-
-      fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
-
-      cupsdAddSelect(fd, (cupsd_selfunc_t)dnssdUpdate, NULL, NULL);
-
-     /*
-      * Then get the port we use for registrations.  If we are not listening
-      * on any non-local ports, there is no sense sharing local printers via
-      * Bonjour...
-      */
-
-      DNSSDPort = 0;
-
-      for (lis = (cupsd_listener_t *)cupsArrayFirst(Listeners);
-          lis;
-          lis = (cupsd_listener_t *)cupsArrayNext(Listeners))
-      {
-       if (httpAddrLocalhost(&(lis->address)))
-         continue;
-
-        DNSSDPort = _httpAddrPort(&(lis->address));
-       break;
-      }
-
-     /*
-      * Create an array to track the printers we share...
-      */
-
-      if (BrowseRemoteProtocols & BROWSE_DNSSD)
-        DNSSDPrinters = cupsArrayNew((cups_array_func_t)dnssdComparePrinters,
-                                    NULL);
-
-     /*
-      * Set the computer name and register the web interface...
-      */
-
-      cupsdUpdateDNSSDName();
-    }
-  }
-#endif /* HAVE_DNSSD */
-
-#ifdef HAVE_LIBSLP
-  if ((BrowseLocalProtocols | BrowseRemoteProtocols) & BROWSE_SLP)
-  {
-   /*
-    * Open SLP handle...
-    */
-
-    if (SLPOpen("en", SLP_FALSE, &BrowseSLPHandle) != SLP_OK)
-    {
-      cupsdLogMessage(CUPSD_LOG_ERROR,
-                      "Unable to open an SLP handle; disabling SLP browsing!");
-      BrowseLocalProtocols &= ~BROWSE_SLP;
-      BrowseRemoteProtocols &= ~BROWSE_SLP;
-      BrowseSLPHandle = NULL;
-
-      if (FatalErrors & CUPSD_FATAL_BROWSE)
-       cupsdEndProcess(getpid(), 0);
-    }
-
-    BrowseSLPRefresh = 0;
-  }
-  else
-    BrowseSLPHandle = NULL;
-#endif /* HAVE_LIBSLP */
-
-#ifdef HAVE_LDAP
-  if ((BrowseLocalProtocols | BrowseRemoteProtocols) & BROWSE_LDAP)
-  {
-    if (!BrowseLDAPDN)
-    {
-      cupsdLogMessage(CUPSD_LOG_ERROR,
-                      "Need to set BrowseLDAPDN to use LDAP browsing!");
-      BrowseLocalProtocols &= ~BROWSE_LDAP;
-      BrowseRemoteProtocols &= ~BROWSE_LDAP;
-
-      if (FatalErrors & CUPSD_FATAL_BROWSE)
-       cupsdEndProcess(getpid(), 0);
-    }
-    else
-    {
-     /*
-      * Open LDAP handle...
-      */
-
-      if ((BrowseLDAPHandle = ldap_connect()) == NULL &&
-          (FatalErrors & CUPSD_FATAL_BROWSE))
-       cupsdEndProcess(getpid(), 0);
-    }
-
-    BrowseLDAPRefresh = 0;
-  }
-#endif /* HAVE_LDAP */
-
- /*
-  * Enable LPD and SMB printer sharing as needed through external programs...
-  */
-
-  if (BrowseLocalProtocols & BROWSE_LPD)
-    update_lpd(1);
-
-  if (BrowseLocalProtocols & BROWSE_SMB)
-    update_smb(1);
-
- /*
-  * Register the individual printers
-  */
-
-  for (p = (cupsd_printer_t *)cupsArrayFirst(Printers);
-       p;
-       p = (cupsd_printer_t *)cupsArrayNext(Printers))
-    if (!(p->type & (CUPS_PRINTER_REMOTE | CUPS_PRINTER_IMPLICIT |
-                     CUPS_PRINTER_SCANNER)))
-      cupsdRegisterPrinter(p);
-}
-
-
-/*
- * 'cupsdStartPolling()' - Start polling servers as needed.
- */
-
-void
-cupsdStartPolling(void)
-{
-  int                  i;              /* Looping var */
-  cupsd_dirsvc_poll_t  *pollp;         /* Current polling server */
-  char                 polld[1024];    /* Poll daemon path */
-  char                 sport[255];     /* Server port */
-  char                 bport[255];     /* Browser port */
-  char                 interval[255];  /* Poll interval */
-  int                  statusfds[2];   /* Status pipe */
-  char                 *argv[6];       /* Arguments */
-  char                 *envp[100];     /* Environment */
-
-
- /*
-  * Don't do anything if we aren't polling...
-  */
-
-  if (NumPolled == 0 || BrowseSocket < 0)
-  {
-    PollPipe         = -1;
-    PollStatusBuffer = NULL;
-    return;
-  }
-
- /*
-  * Setup string arguments for polld, port and interval options.
-  */
-
-  snprintf(polld, sizeof(polld), "%s/daemon/cups-polld", ServerBin);
-
-  sprintf(bport, "%d", BrowsePort);
-
-  if (BrowseInterval)
-    sprintf(interval, "%d", BrowseInterval);
-  else
-    strcpy(interval, "30");
-
-  argv[0] = "cups-polld";
-  argv[2] = sport;
-  argv[3] = interval;
-  argv[4] = bport;
-  argv[5] = NULL;
-
-  cupsdLoadEnv(envp, (int)(sizeof(envp) / sizeof(envp[0])));
-
- /*
-  * Create a pipe that receives the status messages from each
-  * polling daemon...
-  */
-
-  if (cupsdOpenPipe(statusfds))
-  {
-    cupsdLogMessage(CUPSD_LOG_ERROR,
-                    "Unable to create polling status pipes - %s.",
-                   strerror(errno));
-    PollPipe         = -1;
-    PollStatusBuffer = NULL;
-    return;
-  }
-
-  PollPipe         = statusfds[0];
-  PollStatusBuffer = cupsdStatBufNew(PollPipe, "[Poll]");
-
- /*
-  * Run each polling daemon, redirecting stderr to the polling pipe...
-  */
-
-  for (i = 0, pollp = Polled; i < NumPolled; i ++, pollp ++)
-  {
-    sprintf(sport, "%d", pollp->port);
-
-    argv[1] = pollp->hostname;
-
-    if (cupsdStartProcess(polld, argv, envp, -1, -1, statusfds[1], -1, -1,
-                          0, DefaultProfile, NULL, &(pollp->pid)) < 0)
-    {
-      cupsdLogMessage(CUPSD_LOG_ERROR,
-                      "cupsdStartPolling: Unable to fork polling daemon - %s",
-                      strerror(errno));
-      pollp->pid = 0;
-      break;
-    }
-    else
-      cupsdLogMessage(CUPSD_LOG_DEBUG,
-                      "cupsdStartPolling: Started polling daemon for %s:%d, pid = %d",
-                      pollp->hostname, pollp->port, pollp->pid);
-  }
-
-  close(statusfds[1]);
-
- /*
-  * Finally, add the pipe to the input selection set...
-  */
-
-  cupsdAddSelect(PollPipe, (cupsd_selfunc_t)update_polling, NULL, NULL);
-}
-
-
-/*
- * 'cupsdStopBrowsing()' - Stop sending and receiving broadcast information.
- */
-
-void
-cupsdStopBrowsing(void)
-{
-  cupsd_printer_t      *p;             /* Current printer */
-
-
-  if (!Browsing || !(BrowseLocalProtocols | BrowseRemoteProtocols))
-    return;
-
- /*
-  * De-register the individual printers
-  */
-
-  for (p = (cupsd_printer_t *)cupsArrayFirst(Printers);
-       p;
-       p = (cupsd_printer_t *)cupsArrayNext(Printers))
-    if (!(p->type & (CUPS_PRINTER_REMOTE | CUPS_PRINTER_IMPLICIT |
-                     CUPS_PRINTER_SCANNER)))
-      cupsdDeregisterPrinter(p, 1);
-
- /*
-  * Shut down browsing sockets...
-  */
-
-  if (((BrowseLocalProtocols | BrowseRemoteProtocols) & BROWSE_CUPS) &&
-      BrowseSocket >= 0)
-  {
-   /*
-    * Close the socket and remove it from the input selection set.
-    */
-
-#ifdef WIN32
-    closesocket(BrowseSocket);
-#else
-    close(BrowseSocket);
-#endif /* WIN32 */
-
-    cupsdRemoveSelect(BrowseSocket);
-    BrowseSocket = -1;
-  }
-
-#ifdef HAVE_DNSSD
-  if ((BrowseLocalProtocols & BROWSE_DNSSD) && DNSSDRef)
-    dnssdStop();
-#endif /* HAVE_DNSSD */
-
-#ifdef HAVE_LIBSLP
-  if (((BrowseLocalProtocols | BrowseRemoteProtocols) & BROWSE_SLP) &&
-      BrowseSLPHandle)
-  {
-   /*
-    * Close SLP handle...
-    */
-
-    SLPClose(BrowseSLPHandle);
-    BrowseSLPHandle = NULL;
-  }
-#endif /* HAVE_LIBSLP */
-
-#ifdef HAVE_LDAP
-  if (((BrowseLocalProtocols | BrowseRemoteProtocols) & BROWSE_LDAP) &&
-      BrowseLDAPHandle)
-  {
-    ldap_dereg_ou(ServerName, BrowseLDAPDN);
-    ldap_disconnect(BrowseLDAPHandle);
-    BrowseLDAPHandle = NULL;
-  }
-#endif /* HAVE_OPENLDAP */
-
- /*
-  * Disable LPD and SMB printer sharing as needed through external programs...
-  */
-
-  if (BrowseLocalProtocols & BROWSE_LPD)
-    update_lpd(0);
-
-  if (BrowseLocalProtocols & BROWSE_SMB)
-    update_smb(0);
-}
-
-
-/*
- * 'cupsdStopPolling()' - Stop polling servers as needed.
- */
-
-void
-cupsdStopPolling(void)
-{
-  int                  i;              /* Looping var */
-  cupsd_dirsvc_poll_t  *pollp;         /* Current polling server */
-
-
-  if (PollPipe >= 0)
-  {
-    cupsdStatBufDelete(PollStatusBuffer);
-    close(PollPipe);
-
-    cupsdRemoveSelect(PollPipe);
-
-    PollPipe         = -1;
-    PollStatusBuffer = NULL;
-  }
-
-  for (i = 0, pollp = Polled; i < NumPolled; i ++, pollp ++)
-    if (pollp->pid)
-      cupsdEndProcess(pollp->pid, 0);
-}
-
-
-#ifdef HAVE_DNSSD
-/*
- * 'cupsdUpdateDNSSDName()' - Update the computer name we use for browsing...
- */
-
-void
-cupsdUpdateDNSSDName(void)
-{
-  DNSServiceErrorType error;           /* Error from service creation */
-  char         webif[1024];            /* Web interface share name */
-#  ifdef HAVE_SYSTEMCONFIGURATION
-  SCDynamicStoreRef sc;                        /* Context for dynamic store */
-  CFDictionaryRef btmm;                        /* Back-to-My-Mac domains */
-  CFStringEncoding nameEncoding;       /* Encoding of computer name */
-  CFStringRef  nameRef;                /* Host name CFString */
-  char         nameBuffer[1024];       /* C-string buffer */
-#  endif /* HAVE_SYSTEMCONFIGURATION */
-
-
- /*
-  * Only share the web interface and printers when non-local listening is
-  * enabled...
-  */
-
-
-  if (!DNSSDPort)
-    return;
-
- /*
-  * Get the computer name as a c-string...
-  */
-
-#  ifdef HAVE_SYSTEMCONFIGURATION
-  sc = SCDynamicStoreCreate(kCFAllocatorDefault, CFSTR("cupsd"), NULL, NULL);
-
-  if (sc)
-  {
-   /*
-    * Get the computer name from the dynamic store...
-    */
-
-    cupsdClearString(&DNSSDComputerName);
-
-    if ((nameRef = SCDynamicStoreCopyComputerName(sc, &nameEncoding)) != NULL)
-    {
-      if (CFStringGetCString(nameRef, nameBuffer, sizeof(nameBuffer),
-                            kCFStringEncodingUTF8))
-      {
-        cupsdLogMessage(CUPSD_LOG_DEBUG,
-                       "Dynamic store computer name is \"%s\".", nameBuffer);
-       cupsdSetString(&DNSSDComputerName, nameBuffer);
-      }
-
-      CFRelease(nameRef);
-    }
-
-    if (!DNSSDComputerName)
-    {
-     /*
-      * Use the ServerName instead...
-      */
-
-      cupsdLogMessage(CUPSD_LOG_DEBUG,
-                      "Using ServerName \"%s\" as computer name.", ServerName);
-      cupsdSetString(&DNSSDComputerName, ServerName);
-    }
-
-   /*
-    * Get the local hostname from the dynamic store...
-    */
-
-    cupsdClearString(&DNSSDHostName);
-
-    if ((nameRef = SCDynamicStoreCopyLocalHostName(sc)) != NULL)
-    {
-      if (CFStringGetCString(nameRef, nameBuffer, sizeof(nameBuffer),
-                            kCFStringEncodingUTF8))
-      {
-        cupsdLogMessage(CUPSD_LOG_DEBUG,
-                       "Dynamic store host name is \"%s\".", nameBuffer);
-       cupsdSetString(&DNSSDHostName, nameBuffer);
-      }
-
-      CFRelease(nameRef);
-    }
-
-    if (!DNSSDHostName)
-    {
-     /*
-      * Use the ServerName instead...
-      */
-
-      cupsdLogMessage(CUPSD_LOG_DEBUG,
-                      "Using ServerName \"%s\" as host name.", ServerName);
-      cupsdSetString(&DNSSDHostName, ServerName);
-    }
-
-   /*
-    * Get any Back-to-My-Mac domains and add them as aliases...
-    */
-
-    cupsdFreeAliases(DNSSDAlias);
-    DNSSDAlias = NULL;
-
-    btmm = SCDynamicStoreCopyValue(sc, CFSTR("Setup:/Network/BackToMyMac"));
-    if (btmm && CFGetTypeID(btmm) == CFDictionaryGetTypeID())
-    {
-      cupsdLogMessage(CUPSD_LOG_DEBUG, "%d Back to My Mac aliases to add.",
-                     (int)CFDictionaryGetCount(btmm));
-      CFDictionaryApplyFunction(btmm, dnssdAddAlias, NULL);
-    }
-    else if (btmm)
-      cupsdLogMessage(CUPSD_LOG_ERROR,
-                     "Bad Back to My Mac data in dynamic store!");
-    else
-      cupsdLogMessage(CUPSD_LOG_DEBUG, "No Back to My Mac aliases to add.");
-
-    if (btmm)
-      CFRelease(btmm);
-
-    CFRelease(sc);
-  }
-  else
-#  endif /* HAVE_SYSTEMCONFIGURATION */
-  {
-    cupsdSetString(&DNSSDComputerName, ServerName);
-    cupsdSetString(&DNSSDHostName, ServerName);
-  }
-
- /*
-  * Then (re)register the web interface if enabled...
-  */
-
-  if (BrowseWebIF)
-  {
-    if (DNSSDComputerName)
-      snprintf(webif, sizeof(webif), "CUPS @ %s", DNSSDComputerName);
-    else
-      strlcpy(webif, "CUPS Web Interface", sizeof(webif));
-
-    if (WebIFRef)
-      DNSServiceRefDeallocate(WebIFRef);
-
-    WebIFRef = DNSSDRef;
-    if ((error = DNSServiceRegister(&WebIFRef,
-                                   kDNSServiceFlagsShareConnection,
-                                   0, webif, "_http._tcp", NULL,
-                                   NULL, htons(DNSSDPort), 7,
-                                   "\006path=/", dnssdRegisterCallback,
-                                   NULL)) != kDNSServiceErr_NoError)
-      cupsdLogMessage(CUPSD_LOG_ERROR,
-                     "DNS-SD web interface registration failed: %d", error);
-  }
-}
-#endif /* HAVE_DNSSD */
-
-
-#ifdef HAVE_LDAP
-/*
- * 'cupsdUpdateLDAPBrowse()' - Scan for new printers via LDAP...
- */
-
-void
-cupsdUpdateLDAPBrowse(void)
-{
-  char         uri[HTTP_MAX_URI],      /* Printer URI */
-               host[HTTP_MAX_URI],     /* Hostname */
-               resource[HTTP_MAX_URI], /* Resource path */
-               location[1024],         /* Printer location */
-               info[1024],             /* Printer information */
-               make_model[1024],       /* Printer make and model */
-               type_num[30];           /* Printer type number */
-  int          type;                   /* Printer type */
-  int          rc;                     /* LDAP status */
-  int          limit;                  /* Size limit */
-  LDAPMessage  *res,                   /* LDAP search results */
-                 *e;                   /* Current entry from search */
-
-  cupsdLogMessage(CUPSD_LOG_DEBUG2, "UpdateLDAPBrowse: %s", ServerName);
-
-  BrowseLDAPRefresh = time(NULL) + BrowseInterval;
-
- /*
-  * Reconnect if LDAP Handle is invalid...
-  */
-
-  if (! BrowseLDAPHandle)
-  {
-    ldap_reconnect();
-    return;
-  }
-
- /*
-  * Search for cups printers in LDAP directory...
-  */
-
-  rc = ldap_search_rec(BrowseLDAPHandle, BrowseLDAPDN, LDAP_SCOPE_SUBTREE,
-                       "(objectclass=cupsPrinter)", (char **)ldap_attrs, 0, &res);
-
- /*
-  * If ldap search was successfull then exit function
-  * and temporary disable LDAP updates...
-  */
-
-  if (rc != LDAP_SUCCESS)
-  {
-    if (BrowseLDAPUpdate && ((rc == LDAP_SERVER_DOWN) || (rc == LDAP_CONNECT_ERROR)))
-    {
-      BrowseLDAPUpdate = FALSE;
-      cupsdLogMessage(CUPSD_LOG_INFO,
-                      "LDAP update temporary disabled");
-    }
-    return;
-  }
-
- /*
-  * If LDAP updates were disabled, we will reenable them...
-  */
-
-  if (! BrowseLDAPUpdate)
-  {
-    BrowseLDAPUpdate = TRUE;
-    cupsdLogMessage(CUPSD_LOG_INFO,
-                    "LDAP update enabled");
-  }
-
- /*
-  * Count LDAP entries and return if no entry exist...
-  */
-
-  limit = ldap_count_entries(BrowseLDAPHandle, res);
-  cupsdLogMessage(CUPSD_LOG_DEBUG2, "LDAP search returned %d entries", limit);
-  if (limit < 1)
-  {
-    ldap_freeres(res);
-    return;
-  }
-
- /*
-  * Loop through the available printers...
-  */
-
-  for (e = ldap_first_entry(BrowseLDAPHandle, res);
-       e;
-       e = ldap_next_entry(BrowseLDAPHandle, e))
-  {
-   /*
-    * Get the required values from this entry...
-    */
-
-    if (ldap_getval_firststring(BrowseLDAPHandle, e,
-                                "printerDescription", info, sizeof(info)) == -1)
-      continue;
-
-    if (ldap_getval_firststring(BrowseLDAPHandle, e,
-                                "printerLocation", location, sizeof(location)) == -1)
-      continue;
-
-    if (ldap_getval_firststring(BrowseLDAPHandle, e,
-                                "printerMakeAndModel", make_model, sizeof(make_model)) == -1)
-      continue;
-
-    if (ldap_getval_firststring(BrowseLDAPHandle, e,
-                                "printerType", type_num, sizeof(type_num)) == -1)
-      continue;
-
-    type = atoi(type_num);
-
-    if (ldap_getval_firststring(BrowseLDAPHandle, e,
-                                "printerURI", uri, sizeof(uri)) == -1)
-      continue;
-
-   /*
-    * Process the entry as browse data...
-    */
-
-    if (!is_local_queue(uri, host, sizeof(host), resource, sizeof(resource)))
-      process_browse_data(uri, host, resource, type, IPP_PRINTER_IDLE,
-                          location, info, make_model, 0, NULL);
-
-  }
-
-  ldap_freeres(res);
-}
-#endif /* HAVE_LDAP */
-
-
-#ifdef HAVE_LIBSLP
-/*
- * 'cupsdUpdateSLPBrowse()' - Get browsing information via SLP.
- */
-
-void
-cupsdUpdateSLPBrowse(void)
-{
-  slpsrvurl_t  *s,                     /* Temporary list of service URLs */
-               *next;                  /* Next service in list */
-  cupsd_printer_t p;                   /* Printer information */
-  const char   *uri;                   /* Pointer to printer URI */
-  char         host[HTTP_MAX_URI],     /* Host portion of URI */
-               resource[HTTP_MAX_URI]; /* Resource portion of URI */
-
-
- /*
-  * Reset the refresh time...
-  */
-
-  BrowseSLPRefresh = time(NULL) + BrowseInterval;
-
- /*
-  * Poll for remote printers using SLP...
-  */
-
-  s = NULL;
-
-  SLPFindSrvs(BrowseSLPHandle, SLP_CUPS_SRVTYPE, "", "",
-             slp_url_callback, &s);
-
- /*
-  * Loop through the list of available printers...
-  */
-
-  for (; s; s = next)
-  {
-   /*
-    * Save the "next" pointer...
-    */
-
-    next = s->next;
-
-   /*
-    * Load a cupsd_printer_t structure with the SLP service attributes...
-    */
-
-    SLPFindAttrs(BrowseSLPHandle, s->url, "", "", slp_attr_callback, &p);
-
-   /*
-    * Process this printer entry...
-    */
-
-    uri = s->url + SLP_CUPS_SRVLEN + 1;
-
-    if (!strncmp(uri, "http://", 7) || !strncmp(uri, "ipp://", 6))
-    {
-     /*
-      * Pull the URI apart to see if this is a local or remote printer...
-      */
-
-      if (!is_local_queue(uri, host, sizeof(host), resource, sizeof(resource)))
-        process_browse_data(uri, host, resource, p.type, IPP_PRINTER_IDLE,
-                           p.location,  p.info, p.make_model, 0, NULL);
-    }
-
-   /*
-    * Free this listing...
-    */
-
-    cupsdClearString(&p.info);
-    cupsdClearString(&p.location);
-    cupsdClearString(&p.make_model);
-
-    free(s);
-  }
-}
-#endif /* HAVE_LIBSLP */
-
-
-/*
- * 'dequote()' - Remote quotes from a string.
- */
-
-static char *                          /* O - Dequoted string */
-dequote(char       *d,                 /* I - Destination string */
-        const char *s,                 /* I - Source string */
-       int        dlen)                /* I - Destination length */
-{
-  char *dptr;                          /* Pointer into destination */
-
-
-  if (s)
-  {
-    for (dptr = d, dlen --; *s && dlen > 0; s ++)
-      if (*s != '\"')
-      {
-       *dptr++ = *s;
-       dlen --;
-      }
-
-    *dptr = '\0';
-  }
-  else
-    *d = '\0';
-
-  return (d);
-}
-
-
-#ifdef HAVE_DNSSD
-#  ifdef HAVE_COREFOUNDATION
-/*
- * 'dnssdAddAlias()' - Add a DNS-SD alias name.
- */
-
-static void
-dnssdAddAlias(const void *key,         /* I - Key */
-              const void *value,       /* I - Value (domain) */
-             void       *context)      /* I - Unused */
-{
-  char valueStr[1024],                 /* Domain string */
-       hostname[1024];                 /* Complete hostname */
-
-
-  (void)key;
-  (void)context;
-
-  if (CFGetTypeID((CFStringRef)value) == CFStringGetTypeID() &&
-      CFStringGetCString((CFStringRef)value, valueStr, sizeof(valueStr),
-                         kCFStringEncodingUTF8))
-  {
-    snprintf(hostname, sizeof(hostname), "%s.%s", DNSSDHostName, valueStr);
-    if (!DNSSDAlias)
-      DNSSDAlias = cupsArrayNew(NULL, NULL);
-
-    cupsdAddAlias(DNSSDAlias, hostname);
-    cupsdLogMessage(CUPSD_LOG_DEBUG, "Added Back to My Mac ServerAlias %s",
-                   hostname);
-  }
-  else
-    cupsdLogMessage(CUPSD_LOG_ERROR,
-                    "Bad Back to My Mac domain in dynamic store!");
-}
-#  endif /* HAVE_COREFOUNDATION */
-
-
-/*
- * 'dnssdBuildTxtRecord()' - Build a TXT record from printer info.
- */
-
-static char *                          /* O - TXT record */
-dnssdBuildTxtRecord(
-    int             *txt_len,          /* O - TXT record length */
-    cupsd_printer_t *p,                        /* I - Printer information */
-    int             for_lpd)           /* I - 1 = LPD, 0 = IPP */
-{
-  int          i;                      /* Looping var */
-  char         admin_hostname[256],    /* .local hostname for admin page */
-               adminurl_str[256],      /* URL for the admin page */
-               type_str[32],           /* Type to string buffer */
-               state_str[32],          /* State to string buffer */
-               rp_str[1024],           /* Queue name string buffer */
-               air_str[1024],          /* auth-info-required string buffer */
-               *keyvalue[32][2];       /* Table of key/value pairs */
-
-
- /*
-  * Load up the key value pairs...
-  */
-
-  i = 0;
-
-  keyvalue[i  ][0] = "txtvers";
-  keyvalue[i++][1] = "1";
-
-  keyvalue[i  ][0] = "qtotal";
-  keyvalue[i++][1] = "1";
-
-  keyvalue[i  ][0] = "rp";
-  keyvalue[i++][1] = rp_str;
-  if (for_lpd)
-    strlcpy(rp_str, p->name, sizeof(rp_str));
-  else
-    snprintf(rp_str, sizeof(rp_str), "%s/%s",
-            (p->type & CUPS_PRINTER_CLASS) ? "classes" : "printers", p->name);
-
-  keyvalue[i  ][0] = "ty";
-  keyvalue[i++][1] = p->make_model ? p->make_model : "Unknown";
-
-  snprintf(admin_hostname, sizeof(admin_hostname), "%s.local.", DNSSDHostName);
-  httpAssembleURIf(HTTP_URI_CODING_ALL, adminurl_str, sizeof(adminurl_str),
-                   "http", NULL, admin_hostname, DNSSDPort, "/%s/%s",
-                  (p->type & CUPS_PRINTER_CLASS) ? "classes" : "printers",
-                  p->name);
-  keyvalue[i  ][0] = "adminurl";
-  keyvalue[i++][1] = adminurl_str;
-
-  keyvalue[i  ][0] = "note";
-  keyvalue[i++][1] = p->location ? p->location : "";
-
-  keyvalue[i  ][0] = "priority";
-  keyvalue[i++][1] = for_lpd ? "100" : "0";
-
-  keyvalue[i  ][0] = "product";
-  keyvalue[i++][1] = p->pc && p->pc->product ? p->pc->product : "Unknown";
-
-  keyvalue[i  ][0] = "pdl";
-  keyvalue[i++][1] = p->pdl ? p->pdl : "application/postscript";
-
-  if (get_auth_info_required(p, air_str, sizeof(air_str)))
-  {
-    keyvalue[i  ][0] = "air";
-    keyvalue[i++][1] = air_str;
-  }
-
-  keyvalue[i  ][0] = "UUID";
-  keyvalue[i++][1] = p->uuid + 9;
-
-#ifdef HAVE_SSL
-  keyvalue[i  ][0] = "TLS";
-  keyvalue[i++][1] = "1.2";
-#endif /* HAVE_SSL */
-
-  keyvalue[i  ][0] = "Transparent";
-  keyvalue[i++][1] = "F";
-
-  keyvalue[i  ][0] = "Binary";
-  keyvalue[i++][1] = "F";
-
-  keyvalue[i  ][0] = "Fax";
-  keyvalue[i++][1] = (p->type & CUPS_PRINTER_FAX) ? "T" : "F";
-
-  keyvalue[i  ][0] = "Color";
-  keyvalue[i++][1] = (p->type & CUPS_PRINTER_COLOR) ? "T" : "F";
-
-  keyvalue[i  ][0] = "Duplex";
-  keyvalue[i++][1] = (p->type & CUPS_PRINTER_DUPLEX) ? "T" : "F";
-
-  keyvalue[i  ][0] = "Staple";
-  keyvalue[i++][1] = (p->type & CUPS_PRINTER_STAPLE) ? "T" : "F";
-
-  keyvalue[i  ][0] = "Copies";
-  keyvalue[i++][1] = (p->type & CUPS_PRINTER_COPIES) ? "T" : "F";
-
-  keyvalue[i  ][0] = "Collate";
-  keyvalue[i++][1] = (p->type & CUPS_PRINTER_COLLATE) ? "T" : "F";
-
-  keyvalue[i  ][0] = "Punch";
-  keyvalue[i++][1] = (p->type & CUPS_PRINTER_PUNCH) ? "T" : "F";
-
-  keyvalue[i  ][0] = "Bind";
-  keyvalue[i++][1] = (p->type & CUPS_PRINTER_BIND) ? "T" : "F";
-
-  keyvalue[i  ][0] = "Sort";
-  keyvalue[i++][1] = (p->type & CUPS_PRINTER_SORT) ? "T" : "F";
-
-  keyvalue[i  ][0] = "Scan";
-  keyvalue[i++][1] = (p->type & CUPS_PRINTER_MFP) ? "T" : "F";
-
-  snprintf(type_str, sizeof(type_str), "0x%X", p->type | CUPS_PRINTER_REMOTE);
-  snprintf(state_str, sizeof(state_str), "%d", p->state);
-
-  keyvalue[i  ][0] = "printer-state";
-  keyvalue[i++][1] = state_str;
-
-  keyvalue[i  ][0] = "printer-type";
-  keyvalue[i++][1] = type_str;
-
- /*
-  * Then pack them into a proper txt record...
-  */
-
-  return (dnssdPackTxtRecord(txt_len, keyvalue, i));
-}
-
-
-/*
- * 'dnssdComparePrinters()' - Compare the registered names of two printers.
- */
-
-static int                             /* O - Result of comparison */
-dnssdComparePrinters(cupsd_printer_t *a,/* I - First printer */
-                     cupsd_printer_t *b)/* I - Second printer */
-{
-  return (_cups_strcasecmp(a->reg_name, b->reg_name));
-}
-
-
-/*
- * 'dnssdDeregisterPrinter()' - Stop sending broadcast information for a
- *                              printer.
- */
-
-static void
-dnssdDeregisterPrinter(
-    cupsd_printer_t *p)                        /* I - Printer */
-{
-  cupsdLogMessage(CUPSD_LOG_DEBUG2, "dnssdDeregisterPrinter(%s)", p->name);
-
- /*
-  * Closing the socket deregisters the service
-  */
-
-  if (p->ipp_ref)
-  {
-    DNSServiceRefDeallocate(p->ipp_ref);
-    p->ipp_ref = NULL;
-  }
-
-  if (p->ipp_txt)
-  {
-   /*
-    * p->ipp_txt is malloc'd, not _cupsStrAlloc'd...
-    */
-
-    free(p->ipp_txt);
-    p->ipp_txt = NULL;
-  }
-
-  if (p->printer_ref)
-  {
-    DNSServiceRefDeallocate(p->printer_ref);
-    p->printer_ref = NULL;
-  }
-
-  if (p->printer_txt)
-  {
-   /*
-    * p->printer_txt is malloc'd, not _cupsStrAlloc'd...
-    */
-
-    free(p->printer_txt);
-    p->printer_txt = NULL;
-  }
-
- /*
-  * Remove the printer from the array of DNS-SD printers, then clear the
-  * registered name...
-  */
-
-  cupsArrayRemove(DNSSDPrinters, p);
-  cupsdClearString(&p->reg_name);
-}
-
-
-/*
- * 'dnssdPackTxtRecord()' - Pack an array of key/value pairs into the
- *                          TXT record format.
- */
-
-static char *                          /* O - TXT record */
-dnssdPackTxtRecord(int  *txt_len,      /* O - TXT record length */
-                  char *keyvalue[][2], /* I - Table of key value pairs */
-                  int  count)          /* I - Items in table */
-{
-  int  i;                              /* Looping var */
-  int  length;                         /* Length of TXT record */
-  int  length2;                                /* Length of value */
-  char *txtRecord;                     /* TXT record buffer */
-  char *cursor;                                /* Looping pointer */
-
-
- /*
-  * Calculate the buffer size
-  */
-
-  if (count <= 0)
-    return (NULL);
-
-  for (length = i = 0; i < count; i++)
-    length += 1 + strlen(keyvalue[i][0]) +
-             (keyvalue[i][1] ? 1 + strlen(keyvalue[i][1]) : 0);
-
- /*
-  * Allocate and fill it
-  */
-
-  txtRecord = malloc(length);
-  if (txtRecord)
-  {
-    *txt_len = length;
-
-    for (cursor = txtRecord, i = 0; i < count; i++)
-    {
-     /*
-      * Drop in the p-string style length byte followed by the data
-      */
-
-      length  = strlen(keyvalue[i][0]);
-      length2 = keyvalue[i][1] ? 1 + strlen(keyvalue[i][1]) : 0;
-
-      *cursor++ = (unsigned char)(length + length2);
-
-      memcpy(cursor, keyvalue[i][0], length);
-      cursor += length;
-
-      if (length2)
-      {
-        length2 --;
-       *cursor++ = '=';
-       memcpy(cursor, keyvalue[i][1], length2);
-       cursor += length2;
-      }
-    }
-  }
-
-  return (txtRecord);
-}
-
-
-/*
- * 'dnssdRegisterCallback()' - DNSServiceRegister callback.
- */
-
-static void
-dnssdRegisterCallback(
-    DNSServiceRef      sdRef,          /* I - DNS Service reference */
-    DNSServiceFlags    flags,          /* I - Reserved for future use */
-    DNSServiceErrorType        errorCode,      /* I - Error code */
-    const char         *name,          /* I - Service name */
-    const char         *regtype,       /* I - Service type */
-    const char         *domain,        /* I - Domain. ".local" for now */
-    void               *context)       /* I - User-defined context */
-{
-  cupsd_printer_t *p = (cupsd_printer_t *)context;
-                                       /* Current printer */
-
-
-  (void)sdRef;
-  (void)flags;
-  (void)domain;
-
-  cupsdLogMessage(CUPSD_LOG_DEBUG2, "dnssdRegisterCallback(%s, %s) for %s (%s)",
-                  name, regtype, p ? p->name : "Web Interface",
-                 p ? (p->reg_name ? p->reg_name : "(null)") : "NA");
-
-  if (errorCode)
-  {
-    cupsdLogMessage(CUPSD_LOG_ERROR,
-                   "DNSServiceRegister failed with error %d", (int)errorCode);
-    return;
-  }
-  else if (p && (!p->reg_name || _cups_strcasecmp(name, p->reg_name)))
-  {
-    cupsdLogMessage(CUPSD_LOG_INFO, "Using service name \"%s\" for \"%s\"",
-                    name, p->name);
-
-    cupsArrayRemove(DNSSDPrinters, p);
-    cupsdSetString(&p->reg_name, name);
-    cupsArrayAdd(DNSSDPrinters, p);
-
-    LastEvent |= CUPSD_EVENT_PRINTER_MODIFIED;
-  }
-}
-
-
-/*
- * 'dnssdRegisterPrinter()' - Start sending broadcast information for a printer
- *                           or update the broadcast contents.
- */
-
-static void
-dnssdRegisterPrinter(cupsd_printer_t *p)/* I - Printer */
-{
-  DNSServiceErrorType  se;             /* dnssd errors */
-  char                 *ipp_txt,       /* IPP TXT record buffer */
-                       *printer_txt,   /* LPD TXT record buffer */
-                       name[1024],     /* Service name */
-                       *nameptr;       /* Pointer into name */
-  int                  ipp_len,        /* IPP TXT record length */
-                       printer_len,    /* LPD TXT record length */
-                       printer_port;   /* LPD port number */
-  const char           *regtype;       /* Registration type */
-
-
-  cupsdLogMessage(CUPSD_LOG_DEBUG2, "dnssdRegisterPrinter(%s) %s", p->name,
-                  !p->ipp_ref ? "new" : "update");
-
- /*
-  * If per-printer sharing was just disabled make sure we're not
-  * registered before returning.
-  */
-
-  if (!p->shared)
-  {
-    dnssdDeregisterPrinter(p);
-    return;
-  }
-
- /*
-  * The registered name takes the form of "<printer-info> @ <computer name>"...
-  */
-
-  if (p->info && strlen(p->info) > 0)
-  {
-    if (DNSSDComputerName)
-      snprintf(name, sizeof(name), "%s @ %s", p->info, DNSSDComputerName);
-    else
-      strlcpy(name, p->info, sizeof(name));
-  }
-  else if (DNSSDComputerName)
-    snprintf(name, sizeof(name), "%s @ %s", p->name, DNSSDComputerName);
-  else
-    strlcpy(name, p->name, sizeof(name));
-
- /*
-  * If an existing printer was renamed, unregister it and start over...
-  */
-
-  if (p->reg_name && strcmp(p->reg_name, name))
-    dnssdDeregisterPrinter(p);
-
-  if (!p->reg_name)
-  {
-    cupsdSetString(&p->reg_name, name);
-    cupsArrayAdd(DNSSDPrinters, p);
-  }
-
- /*
-  * Register IPP and (optionally) LPD...
-  */
-
-  ipp_len = 0;                         /* anti-compiler-warning-code */
-  ipp_txt = dnssdBuildTxtRecord(&ipp_len, p, 0);
-
-  if (p->ipp_ref &&
-      (ipp_len != p->ipp_len || memcmp(ipp_txt, p->ipp_txt, ipp_len)))
-  {
-   /*
-    * Update the existing registration...
-    */
-
-    /* A TTL of 0 means use record's original value (Radar 3176248) */
-    if ((se = DNSServiceUpdateRecord(p->ipp_ref, NULL, 0, ipp_len, ipp_txt,
-                                    0)) == kDNSServiceErr_NoError)
-    {
-      if (p->ipp_txt)
-       free(p->ipp_txt);
-
-      p->ipp_txt = ipp_txt;
-      p->ipp_len = ipp_len;
-      ipp_txt    = NULL;
-    }
-    else
-    {
-     /*
-      * Failed to update record, lets close this reference and move on...
-      */
-
-      cupsdLogMessage(CUPSD_LOG_ERROR,
-                     "Unable to update IPP DNS-SD record for %s - %d", p->name,
-                     se);
-
-      DNSServiceRefDeallocate(p->ipp_ref);
-      p->ipp_ref = NULL;
-    }
-  }
-
-  if (!p->ipp_ref)
-  {
-   /*
-    * Initial registration.  Use the _fax-ipp regtype for fax queues...
-    */
-
-    regtype = (p->type & CUPS_PRINTER_FAX) ? "_fax-ipp._tcp" : DNSSDRegType;
-
-    cupsdLogMessage(CUPSD_LOG_DEBUG,
-                   "Registering DNS-SD printer %s with name \"%s\" and "
-                   "type \"%s\"", p->name, name, regtype);
-
-   /*
-    * Register the queue, dropping characters as needed until we succeed...
-    */
-
-    nameptr = name + strlen(name);
-
-    do
-    {
-      p->ipp_ref = DNSSDRef;
-      if ((se = DNSServiceRegister(&p->ipp_ref, kDNSServiceFlagsShareConnection,
-                                   0, name, regtype, NULL, NULL,
-                                  htons(DNSSDPort), ipp_len, ipp_txt,
-                                  dnssdRegisterCallback,
-                                  p)) == kDNSServiceErr_BadParam)
-      {
-       /*
-        * Name is too long, drop trailing characters, taking into account
-       * UTF-8 encoding...
-       */
-
-        nameptr --;
-
-        while (nameptr > name && (*nameptr & 0xc0) == 0x80)
-         nameptr --;
-
-        if (nameptr > name)
-          *nameptr = '\0';
-      }
-    }
-    while (se == kDNSServiceErr_BadParam && nameptr > name);
-
-    if (se == kDNSServiceErr_NoError)
-    {
-      p->ipp_txt = ipp_txt;
-      p->ipp_len = ipp_len;
-      ipp_txt    = NULL;
-    }
-    else
-      cupsdLogMessage(CUPSD_LOG_WARN,
-                      "DNS-SD IPP registration of \"%s\" failed: %d",
-                     p->name, se);
-  }
-
-  if (ipp_txt)
-    free(ipp_txt);
-
-  if (BrowseLocalProtocols & BROWSE_LPD)
-  {
-    printer_len  = 0;                  /* anti-compiler-warning-code */
-    printer_port = 515;
-    printer_txt  = dnssdBuildTxtRecord(&printer_len, p, 1);
-  }
-  else
-  {
-    printer_len  = 0;
-    printer_port = 0;
-    printer_txt  = NULL;
-  }
-
-  if (p->printer_ref &&
-      (printer_len != p->printer_len ||
-       memcmp(printer_txt, p->printer_txt, printer_len)))
-  {
-   /*
-    * Update the existing registration...
-    */
-
-    /* A TTL of 0 means use record's original value (Radar 3176248) */
-    if ((se = DNSServiceUpdateRecord(p->printer_ref, NULL, 0, printer_len,
-                                    printer_txt,
-                                    0)) == kDNSServiceErr_NoError)
-    {
-      if (p->printer_txt)
-       free(p->printer_txt);
-
-      p->printer_txt = printer_txt;
-      p->printer_len = printer_len;
-      printer_txt    = NULL;
-    }
-    else
-    {
-     /*
-      * Failed to update record, lets close this reference and move on...
-      */
-
-      cupsdLogMessage(CUPSD_LOG_ERROR,
-                     "Unable to update LPD DNS-SD record for %s - %d",
-                     p->name, se);
-
-      DNSServiceRefDeallocate(p->printer_ref);
-      p->printer_ref = NULL;
-    }
-  }
-
-  if (!p->printer_ref)
-  {
-   /*
-    * Initial registration...
-    */
-
-    cupsdLogMessage(CUPSD_LOG_DEBUG,
-                   "Registering DNS-SD printer %s with name \"%s\" and "
-                   "type \"_printer._tcp\"", p->name, name);
-
-    p->printer_ref = DNSSDRef;
-    if ((se = DNSServiceRegister(&p->printer_ref,
-                                kDNSServiceFlagsShareConnection,
-                                0, name, "_printer._tcp", NULL, NULL,
-                                htons(printer_port), printer_len, printer_txt,
-                                dnssdRegisterCallback,
-                                p)) == kDNSServiceErr_NoError)
-    {
-      p->printer_txt = printer_txt;
-      p->printer_len = printer_len;
-      printer_txt    = NULL;
-    }
-    else
-      cupsdLogMessage(CUPSD_LOG_WARN,
-                     "DNS-SD LPD registration of \"%s\" failed: %d",
-                     p->name, se);
-  }
-
-  if (printer_txt)
-    free(printer_txt);
-}
-
-
-/*
- * 'dnssdStop()' - Stop all DNS-SD registrations.
- */
-
-static void
-dnssdStop(void)
-{
-  cupsd_printer_t      *p;             /* Current printer */
-
-
- /*
-  * De-register the individual printers
-  */
-
-  for (p = (cupsd_printer_t *)cupsArrayFirst(Printers);
-       p;
-       p = (cupsd_printer_t *)cupsArrayNext(Printers))
-    dnssdDeregisterPrinter(p);
-
- /*
-  * Shutdown the rest of the service refs...
-  */
-
-  if (WebIFRef)
-  {
-    DNSServiceRefDeallocate(WebIFRef);
-    WebIFRef = NULL;
-  }
-
-  if (RemoteRef)
-  {
-    DNSServiceRefDeallocate(RemoteRef);
-    RemoteRef = NULL;
-  }
-
-  cupsdRemoveSelect(DNSServiceRefSockFD(DNSSDRef));
-
-  DNSServiceRefDeallocate(DNSSDRef);
-  DNSSDRef = NULL;
-
-  cupsArrayDelete(DNSSDPrinters);
-  DNSSDPrinters = NULL;
-
-  DNSSDPort = 0;
-}
-
-
-/*
- * 'dnssdUpdate()' - Handle DNS-SD queries.
- */
-
-static void
-dnssdUpdate(void)
-{
-  DNSServiceErrorType  sdErr;          /* Service discovery error */
-
-
-  if ((sdErr = DNSServiceProcessResult(DNSSDRef)) != kDNSServiceErr_NoError)
-  {
-    cupsdLogMessage(CUPSD_LOG_ERROR,
-                    "DNS Service Discovery registration error %d!",
-                   sdErr);
-    dnssdStop();
-  }
-}
-#endif /* HAVE_DNSSD */
-
-
-/*
- * 'get_auth_info_required()' - Get the auth-info-required value to advertise.
- */
-
-static char *                          /* O - String or NULL if none */
-get_auth_info_required(
-    cupsd_printer_t *p,                        /* I - Printer */
-    char            *buffer,           /* I - Value buffer */
-    size_t          bufsize)           /* I - Size of value buffer */
-{
-  cupsd_location_t *auth;              /* Pointer to authentication element */
-  char         resource[1024];         /* Printer/class resource path */
-
-
- /*
-  * If auth-info-required is set for this printer, return that...
-  */
-
-  if (p->num_auth_info_required > 0 && strcmp(p->auth_info_required[0], "none"))
-  {
-    int                i;                      /* Looping var */
-    char       *bufptr;                /* Pointer into buffer */
-
-    for (i = 0, bufptr = buffer; i < p->num_auth_info_required; i ++)
-    {
-      if (bufptr >= (buffer + bufsize - 2))
-       break;
-
-      if (i)
-       *bufptr++ = ',';
-
-      strlcpy(bufptr, p->auth_info_required[i], bufsize - (bufptr - buffer));
-      bufptr += strlen(bufptr);
-    }
-
-    return (buffer);
-  }
-
- /*
-  * Figure out the authentication data requirements to advertise...
-  */
-
-  if (p->type & CUPS_PRINTER_CLASS)
-    snprintf(resource, sizeof(resource), "/classes/%s", p->name);
-  else
-    snprintf(resource, sizeof(resource), "/printers/%s", p->name);
-
-  if ((auth = cupsdFindBest(resource, HTTP_POST)) == NULL ||
-      auth->type == CUPSD_AUTH_NONE)
-    auth = cupsdFindPolicyOp(p->op_policy_ptr, IPP_PRINT_JOB);
-
-  if (auth)
-  {
-    int        auth_type;                      /* Authentication type */
-
-    if ((auth_type = auth->type) == CUPSD_AUTH_DEFAULT)
-      auth_type = DefaultAuthType;
-
-    switch (auth_type)
-    {
-      case CUPSD_AUTH_NONE :
-          return (NULL);
-
-      case CUPSD_AUTH_NEGOTIATE :
-         strlcpy(buffer, "negotiate", bufsize);
-         break;
-
-      default :
-         strlcpy(buffer, "username,password", bufsize);
-         break;
-    }
-
-    return (buffer);
-  }
-
-  return ("none");
-}
-
-
-#ifdef __APPLE__
-/*
- * 'get_hostconfig()' - Get an /etc/hostconfig service setting.
- */
-
-static int                             /* O - 1 for YES or AUTOMATIC, 0 for NO */
-get_hostconfig(const char *name)       /* I - Name of service */
-{
-  cups_file_t  *fp;                    /* Hostconfig file */
-  char         line[1024],             /* Line from file */
-               *ptr;                   /* Pointer to value */
-  int          state = 1;              /* State of service */
-
-
- /*
-  * Try opening the /etc/hostconfig file; if we can't open it, assume that
-  * the service is enabled/auto.
-  */
-
-  if ((fp = cupsFileOpen("/etc/hostconfig", "r")) != NULL)
-  {
-   /*
-    * Read lines from the file until we find the service...
-    */
-
-    while (cupsFileGets(fp, line, sizeof(line)))
-    {
-      if (line[0] == '#' || (ptr = strchr(line, '=')) == NULL)
-        continue;
-
-      *ptr++ = '\0';
-
-      if (!_cups_strcasecmp(line, name))
-      {
-       /*
-        * Found the service, see if it is set to "-NO-"...
-       */
-
-       if (!_cups_strncasecmp(ptr, "-NO-", 4))
-         state = 0;
-        break;
-      }
-    }
-
-    cupsFileClose(fp);
-  }
-
-  return (state);
-}
-#endif /* __APPLE__ */
-
-
-/*
- * 'is_local_queue()' - Determine whether the URI points at a local queue.
- */
-
-static int                             /* O - 1 = local, 0 = remote, -1 = bad URI */
-is_local_queue(const char *uri,                /* I - Printer URI */
-               char       *host,       /* O - Host string */
-              int        hostlen,      /* I - Length of host buffer */
-               char       *resource,   /* O - Resource string */
-              int        resourcelen)  /* I - Length of resource buffer */
-{
-  char         scheme[32],             /* Scheme portion of URI */
-               username[HTTP_MAX_URI]; /* Username portion of URI */
-  int          port;                   /* Port portion of URI */
-  cupsd_netif_t        *iface;                 /* Network interface */
-
-
- /*
-  * Pull the URI apart to see if this is a local or remote printer...
-  */
-
-  if (httpSeparateURI(HTTP_URI_CODING_ALL, uri, scheme, sizeof(scheme),
-                      username, sizeof(username), host, hostlen, &port,
-                     resource, resourcelen) < HTTP_URI_OK)
-    return (-1);
-
-  DEBUG_printf(("host=\"%s\", ServerName=\"%s\"\n", host, ServerName));
-
- /*
-  * Check for local server addresses...
-  */
-
-  if (!_cups_strcasecmp(host, ServerName) && port == LocalPort)
-    return (1);
-
-  cupsdNetIFUpdate();
-
-  for (iface = (cupsd_netif_t *)cupsArrayFirst(NetIFList);
-       iface;
-       iface = (cupsd_netif_t *)cupsArrayNext(NetIFList))
-    if (!_cups_strcasecmp(host, iface->hostname) && port == iface->port)
-      return (1);
-
- /*
-  * If we get here, the printer is remote...
-  */
-
-  return (0);
-}
-
-
-/*
- * 'process_browse_data()' - Process new browse data.
- */
-
-static void
-process_browse_data(
-    const char    *uri,                        /* I - URI of printer/class */
-    const char    *host,               /* I - Hostname */
-    const char    *resource,           /* I - Resource path */
-    cups_ptype_t  type,                        /* I - Printer type */
-    ipp_pstate_t  state,               /* I - Printer state */
-    const char    *location,           /* I - Printer location */
-    const char    *info,               /* I - Printer information */
-    const char    *make_model,         /* I - Printer make and model */
-    int                  num_attrs,            /* I - Number of attributes */
-    cups_option_t *attrs)              /* I - Attributes */
-{
-  int          i;                      /* Looping var */
-  int          update;                 /* Update printer attributes? */
-  char         finaluri[HTTP_MAX_URI], /* Final URI for printer */
-               name[IPP_MAX_NAME],     /* Name of printer */
-               newname[IPP_MAX_NAME],  /* New name of printer */
-               *hptr,                  /* Pointer into hostname */
-               *sptr;                  /* Pointer into ServerName */
-  const char   *shortname;             /* Short queue name (queue) */
-  char         local_make_model[IPP_MAX_NAME];
-                                       /* Local make and model */
-  cupsd_printer_t *p;                  /* Printer information */
-  const char   *ipp_options,           /* ipp-options value */
-               *lease_duration,        /* lease-duration value */
-               *uuid;                  /* uuid value */
-  int          is_class;               /* Is this queue a class? */
-
-
-  cupsdLogMessage(CUPSD_LOG_DEBUG2,
-                  "process_browse_data(uri=\"%s\", host=\"%s\", "
-                 "resource=\"%s\", type=%x, state=%d, location=\"%s\", "
-                 "info=\"%s\", make_model=\"%s\", num_attrs=%d, attrs=%p)",
-                 uri, host, resource, type, state,
-                 location ? location : "(nil)", info ? info : "(nil)",
-                 make_model ? make_model : "(nil)", num_attrs, attrs);
-
- /*
-  * Determine if the URI contains any illegal characters in it...
-  */
-
-  if (strncmp(uri, "ipp://", 6) || !host[0] ||
-      (strncmp(resource, "/printers/", 10) &&
-       strncmp(resource, "/classes/", 9)))
-  {
-    cupsdLogMessage(CUPSD_LOG_ERROR, "Bad printer URI in browse data: %s", uri);
-    return;
-  }
-
-  if (strchr(resource, '?') ||
-      (!strncmp(resource, "/printers/", 10) && strchr(resource + 10, '/')) ||
-      (!strncmp(resource, "/classes/", 9) && strchr(resource + 9, '/')))
-  {
-    cupsdLogMessage(CUPSD_LOG_ERROR, "Bad resource in browse data: %s",
-                    resource);
-    return;
-  }
-
- /*
-  * OK, this isn't a local printer; add any remote options...
-  */
-
-  ipp_options = cupsGetOption("ipp-options", num_attrs, attrs);
-
-  if (BrowseRemoteOptions)
-  {
-    if (BrowseRemoteOptions[0] == '?')
-    {
-     /*
-      * Override server-supplied options...
-      */
-
-      snprintf(finaluri, sizeof(finaluri), "%s%s", uri, BrowseRemoteOptions);
-    }
-    else if (ipp_options)
-    {
-     /*
-      * Combine the server and local options...
-      */
-
-      snprintf(finaluri, sizeof(finaluri), "%s?%s+%s", uri, ipp_options,
-               BrowseRemoteOptions);
-    }
-    else
-    {
-     /*
-      * Just use the local options...
-      */
-
-      snprintf(finaluri, sizeof(finaluri), "%s?%s", uri, BrowseRemoteOptions);
-    }
-
-    uri = finaluri;
-  }
-  else if (ipp_options)
-  {
-   /*
-    * Just use the server-supplied options...
-    */
-
-    snprintf(finaluri, sizeof(finaluri), "%s?%s", uri, ipp_options);
-    uri = finaluri;
-  }
-
- /*
-  * See if we already have it listed in the Printers list, and add it if not...
-  */
-
-  type     |= CUPS_PRINTER_REMOTE | CUPS_PRINTER_DISCOVERED;
-  type     &= ~CUPS_PRINTER_IMPLICIT;
-  update   = 0;
-  hptr     = strchr(host, '.');
-  sptr     = strchr(ServerName, '.');
-  is_class = type & CUPS_PRINTER_CLASS;
-  uuid     = cupsGetOption("uuid", num_attrs, attrs);
-
-  if (!ServerNameIsIP && sptr != NULL && hptr != NULL)
-  {
-   /*
-    * Strip the common domain name components...
-    */
-
-    while (hptr != NULL)
-    {
-      if (!_cups_strcasecmp(hptr, sptr))
-      {
-        *hptr = '\0';
-       break;
-      }
-      else
-        hptr = strchr(hptr + 1, '.');
-    }
-  }
-
-  if (is_class)
-  {
-   /*
-    * Remote destination is a class...
-    */
-
-    if (!strncmp(resource, "/classes/", 9))
-      snprintf(name, sizeof(name), "%s@%s", resource + 9, host);
-    else
-      return;
-
-    shortname = resource + 9;
-  }
-  else
-  {
-   /*
-    * Remote destination is a printer...
-    */
-
-    if (!strncmp(resource, "/printers/", 10))
-      snprintf(name, sizeof(name), "%s@%s", resource + 10, host);
-    else
-      return;
-
-    shortname = resource + 10;
-  }
-
-  if (hptr && !*hptr)
-    *hptr = '.';                       /* Resource FQDN */
-
-  if ((p = cupsdFindDest(name)) == NULL && BrowseShortNames)
-  {
-   /*
-    * Long name doesn't exist, try short name...
-    */
-
-    cupsdLogMessage(CUPSD_LOG_DEBUG, "process_browse_data: %s not found...",
-                    name);
-
-    if ((p = cupsdFindDest(shortname)) == NULL)
-    {
-     /*
-      * Short name doesn't exist, use it for this shared queue.
-      */
-
-      cupsdLogMessage(CUPSD_LOG_DEBUG2, "process_browse_data: %s not found...",
-                     shortname);
-      strlcpy(name, shortname, sizeof(name));
-    }
-    else
-    {
-     /*
-      * Short name exists...
-      */
-
-      cupsdLogMessage(CUPSD_LOG_DEBUG2,
-                      "process_browse_data: %s found, type=%x, hostname=%s...",
-                     shortname, p->type, p->hostname ? p->hostname : "(nil)");
-
-      if (p->type & CUPS_PRINTER_IMPLICIT)
-        p = NULL;                      /* Don't replace implicit classes */
-      else if (p->hostname && _cups_strcasecmp(p->hostname, host))
-      {
-       /*
-       * Short name exists but is for a different host.  If this is a remote
-       * queue, rename it and use the long name...
-       */
-
-       if (p->type & CUPS_PRINTER_REMOTE)
-       {
-         cupsdLogMessage(CUPSD_LOG_DEBUG,
-                         "Renamed remote %s \"%s\" to \"%s@%s\"...",
-                         is_class ? "class" : "printer", p->name, p->name,
-                         p->hostname);
-         cupsdAddEvent(CUPSD_EVENT_PRINTER_DELETED, p, NULL,
-                       "%s \'%s\' deleted by directory services.",
-                       is_class ? "Class" : "Printer", p->name);
-
-         snprintf(newname, sizeof(newname), "%s@%s", p->name, p->hostname);
-         cupsdRenamePrinter(p, newname);
-
-         cupsdAddEvent(CUPSD_EVENT_PRINTER_ADDED, p, NULL,
-                       "%s \'%s\' added by directory services.",
-                       is_class ? "Class" : "Printer", p->name);
-       }
-
-       /*
-        * Force creation with long name...
-       */
-
-       p = NULL;
-      }
-    }
-  }
-  else if (p)
-    cupsdLogMessage(CUPSD_LOG_DEBUG2,
-                   "process_browse_data: %s found, type=%x, hostname=%s...",
-                   name, p->type, p->hostname ? p->hostname : "(nil)");
-
-  if (!p)
-  {
-   /*
-    * Queue doesn't exist; add it...
-    */
-
-    if (is_class)
-      p = cupsdAddClass(name);
-    else
-      p = cupsdAddPrinter(name);
-
-    if (!p)
-      return;
-
-    cupsdClearString(&(p->hostname));
-
-    cupsdLogMessage(CUPSD_LOG_DEBUG, "Added remote %s \"%s\"...",
-                    is_class ? "class" : "printer", name);
-
-    cupsdAddEvent(CUPSD_EVENT_PRINTER_ADDED, p, NULL,
-                 "%s \'%s\' added by directory services.",
-                 is_class ? "Class" : "Printer", name);
-
-   /*
-    * Force the URI to point to the real server...
-    */
-
-    p->type      = type & ~CUPS_PRINTER_REJECTING;
-    p->accepting = 1;
-
-    cupsdMarkDirty(CUPSD_DIRTY_PRINTCAP);
-  }
-
-  if (!p->hostname)
-  {
-   /*
-    * Hostname not set, so this must be a cached remote printer
-    * that was created for a pending print job...
-    */
-
-    cupsdSetString(&p->hostname, host);
-    cupsdSetString(&p->uri, uri);
-    cupsdSetString(&p->device_uri, uri);
-    update = 1;
-
-    cupsdMarkDirty(CUPSD_DIRTY_REMOTE);
-  }
-
- /*
-  * Update the state...
-  */
-
-  p->state       = state;
-  p->browse_time = time(NULL);
-
-  if ((lease_duration = cupsGetOption("lease-duration", num_attrs,
-                                      attrs)) != NULL)
-  {
-   /*
-    * Grab the lease-duration for the browse data; anything less then 1
-    * second or more than 1 week gets the default BrowseTimeout...
-    */
-
-    i = atoi(lease_duration);
-    if (i < 1 || i > 604800)
-      i = BrowseTimeout;
-
-    p->browse_expire = p->browse_time + i;
-  }
-  else
-    p->browse_expire = p->browse_time + BrowseTimeout;
-
-  if (type & CUPS_PRINTER_REJECTING)
-  {
-    type &= ~CUPS_PRINTER_REJECTING;
-
-    if (p->accepting)
-    {
-      update       = 1;
-      p->accepting = 0;
-    }
-  }
-  else if (!p->accepting)
-  {
-    update       = 1;
-    p->accepting = 1;
-  }
-
-  if (p->type != type)
-  {
-    p->type = type;
-    update  = 1;
-  }
-
-  if (uuid && strcmp(p->uuid, uuid))
-  {
-    cupsdSetString(&p->uuid, uuid);
-    update = 1;
-  }
-
-  if (location && (!p->location || strcmp(p->location, location)))
-  {
-    cupsdSetString(&p->location, location);
-    update = 1;
-  }
-
-  if (info && (!p->info || strcmp(p->info, info)))
-  {
-    cupsdSetString(&p->info, info);
-    update = 1;
-
-    cupsdMarkDirty(CUPSD_DIRTY_PRINTCAP | CUPSD_DIRTY_REMOTE);
-  }
-
-  if (!make_model || !make_model[0])
-  {
-    if (is_class)
-      snprintf(local_make_model, sizeof(local_make_model),
-               "Remote Class on %s", host);
-    else
-      snprintf(local_make_model, sizeof(local_make_model),
-               "Remote Printer on %s", host);
-  }
-  else
-    snprintf(local_make_model, sizeof(local_make_model),
-             "%s on %s", make_model, host);
-
-  if (!p->make_model || strcmp(p->make_model, local_make_model))
-  {
-    cupsdSetString(&p->make_model, local_make_model);
-    update = 1;
-  }
-
-  if (p->num_options)
-  {
-    if (!update && !(type & CUPS_PRINTER_DELETE))
-    {
-     /*
-      * See if we need to update the attributes...
-      */
-
-      if (p->num_options != num_attrs)
-       update = 1;
-      else
-      {
-       for (i = 0; i < num_attrs; i ++)
-          if (strcmp(attrs[i].name, p->options[i].name) ||
-             (!attrs[i].value != !p->options[i].value) ||
-             (attrs[i].value && strcmp(attrs[i].value, p->options[i].value)))
-          {
-           update = 1;
-           break;
-          }
-      }
-    }
-
-   /*
-    * Free the old options...
-    */
-
-    cupsFreeOptions(p->num_options, p->options);
-  }
-
-  p->num_options = num_attrs;
-  p->options     = attrs;
-
-  if (type & CUPS_PRINTER_DELETE)
-  {
-    cupsdAddEvent(CUPSD_EVENT_PRINTER_DELETED, p, NULL,
-                  "%s \'%s\' deleted by directory services.",
-                 is_class ? "Class" : "Printer", p->name);
-
-    cupsdExpireSubscriptions(p, NULL);
-
-    cupsdDeletePrinter(p, 1);
-    cupsdUpdateImplicitClasses();
-    cupsdMarkDirty(CUPSD_DIRTY_PRINTCAP | CUPSD_DIRTY_REMOTE);
-  }
-  else if (update)
-  {
-    cupsdSetPrinterAttrs(p);
-    cupsdUpdateImplicitClasses();
-  }
-
- /*
-  * See if we have a default printer...  If not, make the first network
-  * default printer the default.
-  */
-
-  if (DefaultPrinter == NULL && Printers != NULL && UseNetworkDefault)
-  {
-   /*
-    * Find the first network default printer and use it...
-    */
-
-    for (p = (cupsd_printer_t *)cupsArrayFirst(Printers);
-         p;
-        p = (cupsd_printer_t *)cupsArrayNext(Printers))
-      if (p->type & CUPS_PRINTER_DEFAULT)
-      {
-        DefaultPrinter = p;
-        cupsdMarkDirty(CUPSD_DIRTY_PRINTCAP | CUPSD_DIRTY_REMOTE);
-       break;
-      }
-  }
-
- /*
-  * Do auto-classing if needed...
-  */
-
-  process_implicit_classes();
-}
-
-
-/*
- * 'process_implicit_classes()' - Create/update implicit classes as needed.
- */
-
-static void
-process_implicit_classes(void)
+static char *                          /* O - TXT record */
+dnssdBuildTxtRecord(
+    int             *txt_len,          /* O - TXT record length */
+    cupsd_printer_t *p,                        /* I - Printer information */
+    int             for_lpd)           /* I - 1 = LPD, 0 = IPP */
 {
   int          i;                      /* Looping var */
-  int          update;                 /* Update printer attributes? */
-  char         name[IPP_MAX_NAME],     /* Name of printer */
-               *hptr;                  /* Pointer into hostname */
-  cupsd_printer_t *p,                  /* Printer information */
-               *pclass,                /* Printer class */
-               *first;                 /* First printer in class */
-  int          offset,                 /* Offset of name */
-               len;                    /* Length of name */
-
-
-  if (!ImplicitClasses || !Printers)
-    return;
-
- /*
-  * Loop through all available printers and create classes as needed...
-  */
-
-  for (p = (cupsd_printer_t *)cupsArrayFirst(Printers), len = 0, offset = 0,
-           update = 0, pclass = NULL, first = NULL;
-       p != NULL;
-       p = (cupsd_printer_t *)cupsArrayNext(Printers))
-  {
-   /*
-    * Skip implicit classes...
-    */
-
-    if (p->type & CUPS_PRINTER_IMPLICIT)
-    {
-      len = 0;
-      continue;
-    }
-
-   /*
-    * If len == 0, get the length of this printer name up to the "@"
-    * sign (if any).
-    */
-
-    cupsArraySave(Printers);
-
-    if (len > 0 &&
-       !_cups_strncasecmp(p->name, name + offset, len) &&
-       (p->name[len] == '\0' || p->name[len] == '@'))
-    {
-     /*
-      * We have more than one printer with the same name; see if
-      * we have a class, and if this printer is a member...
-      */
-
-      if (pclass && _cups_strcasecmp(pclass->name, name))
-      {
-       if (update)
-         cupsdSetPrinterAttrs(pclass);
-
-       update = 0;
-       pclass = NULL;
-      }
-
-      if (!pclass && (pclass = cupsdFindDest(name)) == NULL)
-      {
-       /*
-       * Need to add the class...
-       */
-
-       pclass = cupsdAddPrinter(name);
-       cupsArrayAdd(ImplicitPrinters, pclass);
-
-       pclass->type      |= CUPS_PRINTER_IMPLICIT;
-       pclass->accepting = 1;
-       pclass->state     = IPP_PRINTER_IDLE;
-
-        cupsdSetString(&pclass->location, p->location);
-        cupsdSetString(&pclass->info, p->info);
-
-        cupsdSetString(&pclass->job_sheets[0], p->job_sheets[0]);
-        cupsdSetString(&pclass->job_sheets[1], p->job_sheets[1]);
-
-        update = 1;
-
-       cupsdMarkDirty(CUPSD_DIRTY_PRINTCAP | CUPSD_DIRTY_REMOTE);
-
-        cupsdLogMessage(CUPSD_LOG_DEBUG, "Added implicit class \"%s\"...",
-                       name);
-       cupsdAddEvent(CUPSD_EVENT_PRINTER_ADDED, p, NULL,
-                      "Implicit class \'%s\' added by directory services.",
-                     name);
-      }
-
-      if (first != NULL)
-      {
-        for (i = 0; i < pclass->num_printers; i ++)
-         if (pclass->printers[i] == first)
-           break;
-
-        if (i >= pclass->num_printers)
-       {
-         first->in_implicit_class = 1;
-         cupsdAddPrinterToClass(pclass, first);
-        }
-
-       first = NULL;
-      }
-
-      for (i = 0; i < pclass->num_printers; i ++)
-       if (pclass->printers[i] == p)
-         break;
-
-      if (i >= pclass->num_printers)
-      {
-       p->in_implicit_class = 1;
-       cupsdAddPrinterToClass(pclass, p);
-       update = 1;
-      }
-    }
-    else
-    {
-     /*
-      * First time around; just get name length and mark it as first
-      * in the list...
-      */
-
-      if ((hptr = strchr(p->name, '@')) != NULL)
-       len = hptr - p->name;
-      else
-       len = strlen(p->name);
-
-      if (len >= sizeof(name))
-      {
-       /*
-       * If the printer name length somehow is greater than we normally allow,
-       * skip this printer...
-       */
-
-       len = 0;
-       cupsArrayRestore(Printers);
-       continue;
-      }
-
-      strncpy(name, p->name, len);
-      name[len] = '\0';
-      offset    = 0;
-
-      if ((first = (hptr ? cupsdFindDest(name) : p)) != NULL &&
-         !(first->type & CUPS_PRINTER_IMPLICIT))
-      {
-       /*
-       * Can't use same name as a local printer; add "Any" to the
-       * front of the name, unless we have explicitly disabled
-       * the "ImplicitAnyClasses"...
-       */
-
-        if (ImplicitAnyClasses && len < (sizeof(name) - 4))
-       {
-        /*
-         * Add "Any" to the class name...
-         */
-
-          strcpy(name, "Any");
-          strncpy(name + 3, p->name, len);
-         name[len + 3] = '\0';
-         offset        = 3;
-       }
-       else
-       {
-        /*
-         * Don't create an implicit class if we have a local printer
-         * with the same name...
-         */
-
-         len = 0;
-          cupsArrayRestore(Printers);
-         continue;
-       }
-      }
-
-      first = p;
-    }
-
-    cupsArrayRestore(Printers);
-  }
-
- /*
-  * Update the last printer class as needed...
-  */
-
-  if (pclass && update)
-    cupsdSetPrinterAttrs(pclass);
-}
-
-
-/*
- * 'send_cups_browse()' - Send new browsing information using the CUPS
- *                        protocol.
- */
-
-static void
-send_cups_browse(cupsd_printer_t *p)   /* I - Printer to send */
-{
-  int                  i;              /* Looping var */
-  cups_ptype_t         type;           /* Printer type */
-  cupsd_dirsvc_addr_t  *b;             /* Browse address */
-  int                  bytes;          /* Length of packet */
-  char                 packet[1453],   /* Browse data packet */
-                       uri[1024],      /* Printer URI */
-                       location[1024], /* printer-location */
-                       info[1024],     /* printer-info */
-                       make_model[1024],
-                                       /* printer-make-and-model */
-                       air[1024];      /* auth-info-required */
-  cupsd_netif_t                *iface;         /* Network interface */
-
-
- /*
-  * Figure out the printer type value...
-  */
-
-  type = p->type | CUPS_PRINTER_REMOTE;
-
-  if (!p->accepting)
-    type |= CUPS_PRINTER_REJECTING;
-
-  if (p == DefaultPrinter)
-    type |= CUPS_PRINTER_DEFAULT;
-
- /*
-  * Remove quotes from printer-info, printer-location, and
-  * printer-make-and-model attributes...
-  */
-
-  dequote(location, p->location, sizeof(location));
-  dequote(info, p->info, sizeof(info));
-
-  if (p->make_model)
-    dequote(make_model, p->make_model, sizeof(make_model));
-  else if (p->type & CUPS_PRINTER_CLASS)
-  {
-    if (p->num_printers > 0 && p->printers[0]->make_model)
-      strlcpy(make_model, p->printers[0]->make_model, sizeof(make_model));
-    else
-      strlcpy(make_model, "Local Printer Class", sizeof(make_model));
-  }
-  else if (p->raw)
-    strlcpy(make_model, "Local Raw Printer", sizeof(make_model));
-  else
-    strlcpy(make_model, "Local System V Printer", sizeof(make_model));
-
-  if (get_auth_info_required(p, packet, sizeof(packet)))
-    snprintf(air, sizeof(air), " auth-info-required=%s", packet);
-  else
-    air[0] = '\0';
-
- /*
-  * Send a packet to each browse address...
-  */
-
-  for (i = NumBrowsers, b = Browsers; i > 0; i --, b ++)
-    if (b->iface[0])
-    {
-     /*
-      * Send the browse packet to one or more interfaces...
-      */
-
-      if (!strcmp(b->iface, "*"))
-      {
-       /*
-        * Send to all local interfaces...
-       */
-
-        cupsdNetIFUpdate();
-
-       for (iface = (cupsd_netif_t *)cupsArrayFirst(NetIFList);
-            iface;
-            iface = (cupsd_netif_t *)cupsArrayNext(NetIFList))
-       {
-        /*
-         * Only send to local, IPv4 interfaces...
-         */
-
-         if (!iface->is_local || !iface->port ||
-             iface->address.addr.sa_family != AF_INET)
-           continue;
-
-         httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
-                          iface->hostname, iface->port,
-                          (p->type & CUPS_PRINTER_CLASS) ? "/classes/%s" :
-                                                           "/printers/%s",
-                          p->name);
-         snprintf(packet, sizeof(packet),
-                  "%x %x %s \"%s\" \"%s\" \"%s\" %s%s uuid=%s\n",
-                  type, p->state, uri, location, info, make_model,
-                  p->browse_attrs ? p->browse_attrs : "", air, p->uuid);
-
-         bytes = strlen(packet);
-
-         cupsdLogMessage(CUPSD_LOG_DEBUG2,
-                         "cupsdSendBrowseList: (%d bytes to \"%s\") %s", bytes,
-                         iface->name, packet);
-
-          iface->broadcast.ipv4.sin_port = htons(BrowsePort);
-
-         sendto(BrowseSocket, packet, bytes, 0,
-                (struct sockaddr *)&(iface->broadcast),
-                httpAddrLength(&(iface->broadcast)));
-        }
-      }
-      else if ((iface = cupsdNetIFFind(b->iface)) != NULL)
-      {
-       /*
-        * Send to the named interface using the IPv4 address...
-       */
-
-        while (iface)
-         if (strcmp(b->iface, iface->name))
-         {
-           iface = NULL;
-           break;
-         }
-         else if (iface->address.addr.sa_family == AF_INET && iface->port)
-           break;
-         else
-            iface = (cupsd_netif_t *)cupsArrayNext(NetIFList);
-
-        if (iface)
-       {
-         httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
-                          iface->hostname, iface->port,
-                          (p->type & CUPS_PRINTER_CLASS) ? "/classes/%s" :
-                                                           "/printers/%s",
-                          p->name);
-         snprintf(packet, sizeof(packet),
-                  "%x %x %s \"%s\" \"%s\" \"%s\" %s%s uuid=%s\n",
-                  type, p->state, uri, location, info, make_model,
-                  p->browse_attrs ? p->browse_attrs : "", air, p->uuid);
-
-         bytes = strlen(packet);
-
-         cupsdLogMessage(CUPSD_LOG_DEBUG2,
-                         "cupsdSendBrowseList: (%d bytes to \"%s\") %s", bytes,
-                         iface->name, packet);
-
-          iface->broadcast.ipv4.sin_port = htons(BrowsePort);
-
-         sendto(BrowseSocket, packet, bytes, 0,
-                (struct sockaddr *)&(iface->broadcast),
-                httpAddrLength(&(iface->broadcast)));
-        }
-      }
-    }
-    else
-    {
-     /*
-      * Send the browse packet to the indicated address using
-      * the default server name...
-      */
-
-      snprintf(packet, sizeof(packet),
-               "%x %x %s \"%s\" \"%s\" \"%s\" %s%s uuid=%s\n",
-                      type, p->state, p->uri, location, info, make_model,
-              p->browse_attrs ? p->browse_attrs : "", air, p->uuid);
-
-      bytes = strlen(packet);
-      cupsdLogMessage(CUPSD_LOG_DEBUG2,
-                      "cupsdSendBrowseList: (%d bytes) %s", bytes, packet);
-
-      if (sendto(BrowseSocket, packet, bytes, 0,
-                (struct sockaddr *)&(b->to),
-                httpAddrLength(&(b->to))) <= 0)
-      {
-       /*
-        * Unable to send browse packet, so remove this address from the
-       * list...
-       */
-
-       cupsdLogMessage(CUPSD_LOG_ERROR,
-                       "cupsdSendBrowseList: sendto failed for browser "
-                       "%d - %s.",
-                       (int)(b - Browsers + 1), strerror(errno));
-
-        if (i > 1)
-         memmove(b, b + 1, (i - 1) * sizeof(cupsd_dirsvc_addr_t));
-
-       b --;
-       NumBrowsers --;
-      }
-    }
-}
-
-
-#ifdef HAVE_LDAP
-/*
- * 'ldap_search_rec()' - LDAP Search with reconnect
- */
-
-static int                             /* O - Return code */
-ldap_search_rec(LDAP        *ld,       /* I - LDAP handler */
-                char        *base,     /* I - Base dn */
-                int         scope,     /* I - LDAP search scope */
-                char        *filter,   /* I - Filter string */
-                char        *attrs[],  /* I - Requested attributes */
-                int         attrsonly, /* I - Return only attributes? */
-                LDAPMessage **res)     /* I - LDAP handler */
-{
-  int  rc;                             /* Return code */
-  LDAP  *ldr;                          /* LDAP handler after reconnect */
-
-
-#  if defined(HAVE_OPENLDAP) && LDAP_API_VERSION > 3000
-  rc = ldap_search_ext_s(ld, base, scope, filter, attrs, attrsonly, NULL, NULL,
-                         NULL, LDAP_NO_LIMIT, res);
-#  else
-  rc = ldap_search_s(ld, base, scope, filter, attrs, attrsonly, res);
-#  endif /* defined(HAVE_OPENLDAP) && LDAP_API_VERSION > 3000 */
-
- /*
-  * If we have a connection problem try again...
-  */
-
-  if (rc == LDAP_SERVER_DOWN || rc == LDAP_CONNECT_ERROR)
-  {
-    cupsdLogMessage(CUPSD_LOG_ERROR,
-                    "LDAP search failed with status %d: %s",
-                     rc, ldap_err2string(rc));
-    cupsdLogMessage(CUPSD_LOG_INFO,
-                    "We try the LDAP search once again after reconnecting to "
-                   "the server");
-    ldap_freeres(*res);
-    ldr = ldap_reconnect();
-
-#  if defined(HAVE_OPENLDAP) && LDAP_API_VERSION > 3000
-    rc = ldap_search_ext_s(ldr, base, scope, filter, attrs, attrsonly, NULL,
-                           NULL, NULL, LDAP_NO_LIMIT, res);
-#  else
-    rc = ldap_search_s(ldr, base, scope, filter, attrs, attrsonly, res);
-#  endif /* defined(HAVE_OPENLDAP) && LDAP_API_VERSION > 3000 */
-  }
-
-  if (rc == LDAP_NO_SUCH_OBJECT)
-    cupsdLogMessage(CUPSD_LOG_DEBUG,
-                    "ldap_search_rec: LDAP entry/object not found");
-  else if (rc != LDAP_SUCCESS)
-    cupsdLogMessage(CUPSD_LOG_ERROR,
-                    "ldap_search_rec: LDAP search failed with status %d: %s",
-                     rc, ldap_err2string(rc));
-
-  if (rc != LDAP_SUCCESS)
-    ldap_freeres(*res);
-
-  return (rc);
-}
-
-
-/*
- * 'ldap_freeres()' - Free LDAPMessage
- */
-
-static void
-ldap_freeres(LDAPMessage *entry)       /* I - LDAP handler */
-{
-  int  rc;                             /* Return value */
-
-
-  rc = ldap_msgfree(entry);
-  if (rc == -1)
-    cupsdLogMessage(CUPSD_LOG_WARN, "Can't free LDAPMessage!");
-  else if (rc == 0)
-    cupsdLogMessage(CUPSD_LOG_DEBUG2, "Freeing LDAPMessage was unnecessary");
-}
-
-
-/*
- * 'ldap_getval_char()' - Get first LDAP value and convert to string
- */
-
-static int                             /* O - Return code */
-ldap_getval_firststring(
-    LDAP          *ld,                 /* I - LDAP handler */
-    LDAPMessage   *entry,              /* I - LDAP message or search result */
-    char          *attr,               /* I - the wanted attribute  */
-    char          *retval,             /* O - String to return */
-    unsigned long maxsize)             /* I - Max string size */
-{
-  char                 *dn;            /* LDAP DN */
-  int                  rc = 0;         /* Return code */
-#  if defined(HAVE_OPENLDAP) && LDAP_API_VERSION > 3000
-  struct berval                **bval;         /* LDAP value array */
-  unsigned long                size;           /* String size */
-
-
- /*
-  * Get value from LDAPMessage...
-  */
-
-  if ((bval = ldap_get_values_len(ld, entry, attr)) == NULL)
-  {
-    rc = -1;
-    dn = ldap_get_dn(ld, entry);
-    cupsdLogMessage(CUPSD_LOG_WARN,
-                    "Failed to get LDAP value %s for %s!",
-                    attr, dn);
-    ldap_memfree(dn);
-  }
-  else
-  {
-   /*
-    * Check size and copy value into our string...
-    */
-
-    size = maxsize;
-    if (size < (bval[0]->bv_len + 1))
-    {
-      rc = -1;
-      dn = ldap_get_dn(ld, entry);
-      cupsdLogMessage(CUPSD_LOG_WARN,
-                      "Attribute %s is too big! (dn: %s)",
-                      attr, dn);
-      ldap_memfree(dn);
-    }
-    else
-      size = bval[0]->bv_len + 1;
-
-    strlcpy(retval, bval[0]->bv_val, size);
-    ldap_value_free_len(bval);
-  }
-#  else
-  char **value;                        /* LDAP value */
-
- /*
-  * Get value from LDAPMessage...
-  */
-
-  if ((value = (char **)ldap_get_values(ld, entry, attr)) == NULL)
-  {
-    rc = -1;
-    dn = ldap_get_dn(ld, entry);
-    cupsdLogMessage(CUPSD_LOG_WARN, "Failed to get LDAP value %s for %s!",
-                    attr, dn);
-    ldap_memfree(dn);
-  }
-  else
-  {
-    strlcpy(retval, *value, maxsize);
-    ldap_value_free(value);
-  }
-#  endif /* defined(HAVE_OPENLDAP) && LDAP_API_VERSION > 3000 */
-
-  return (rc);
-}
-
-
-/*
- * 'send_ldap_ou()' - Send LDAP ou registrations.
- */
+  char         admin_hostname[256],    /* .local hostname for admin page */
+               adminurl_str[256],      /* URL for the admin page */
+               type_str[32],           /* Type to string buffer */
+               state_str[32],          /* State to string buffer */
+               rp_str[1024],           /* Queue name string buffer */
+               air_str[1024],          /* auth-info-required string buffer */
+               *keyvalue[32][2];       /* Table of key/value pairs */
 
-static void
-send_ldap_ou(char *ou,                 /* I - Servername/ou to register */
-             char *basedn,             /* I - Our base dn */
-             char *descstring)         /* I - Description for ou */
-{
-  int           i;                      /* Looping var... */
-  LDAPMod       mods[3];                /* The 3 attributes we will be adding */
-  LDAPMod       *pmods[4];              /* Pointers to the 3 attributes + NULL */
-  LDAPMessage   *res,                   /* Search result token */
-               *e;                     /* Current entry from search */
-  int           rc;                     /* LDAP status */
-  int           rcmod;                  /* LDAP status for modifications */
-  char          dn[1024],               /* DN of the organizational unit we are adding */
-                *desc[2],               /* Change records */
-                *ou_value[2];
-  char         old_desc[1024];         /* Old description */
-  static const char * const objectClass_values[] =
-               {                       /* The 2 objectClass's we use in */
-                 "top",                /* our LDAP entries              */
-                 "organizationalUnit",
-                 NULL
-               };
-  static const char * const ou_attrs[] =/* CUPS LDAP attributes */
-               {
-                 "description",
-                 NULL
-               };
-
-
-  cupsdLogMessage(CUPSD_LOG_DEBUG2, "send_ldap_ou: %s", ou);
 
  /*
-  * Reconnect if LDAP Handle is invalid...
+  * Load up the key value pairs...
   */
 
-  if (!BrowseLDAPHandle)
-  {
-    cupsdLogMessage(CUPSD_LOG_DEBUG2,
-                    "send_ldap_ou: LDAP Handle is invalid. Try reconnecting...");
-    ldap_reconnect();
-    return;
-  }
+  i = 0;
 
- /*
-  * Prepare ldap search...
-  */
+  keyvalue[i  ][0] = "txtvers";
+  keyvalue[i++][1] = "1";
 
-  snprintf(dn, sizeof(dn), "ou=%s, %s", ou, basedn);
-  cupsdLogMessage(CUPSD_LOG_DEBUG2, "send_ldap_ou: dn=\"%s\"", dn);
+  keyvalue[i  ][0] = "qtotal";
+  keyvalue[i++][1] = "1";
 
-  ou_value[0] = ou;
-  ou_value[1] = NULL;
-  desc[0]     = descstring;
-  desc[1]     = NULL;
+  keyvalue[i  ][0] = "rp";
+  keyvalue[i++][1] = rp_str;
+  if (for_lpd)
+    strlcpy(rp_str, p->name, sizeof(rp_str));
+  else
+    snprintf(rp_str, sizeof(rp_str), "%s/%s",
+            (p->type & CUPS_PRINTER_CLASS) ? "classes" : "printers", p->name);
 
-  mods[0].mod_type   = "ou";
-  mods[0].mod_values = ou_value;
-  mods[1].mod_type   = "description";
-  mods[1].mod_values = desc;
-  mods[2].mod_type   = "objectClass";
-  mods[2].mod_values = (char **)objectClass_values;
+  keyvalue[i  ][0] = "ty";
+  keyvalue[i++][1] = p->make_model ? p->make_model : "Unknown";
 
-  rc = ldap_search_rec(BrowseLDAPHandle, dn, LDAP_SCOPE_BASE, NULL,
-                       (char **)ou_attrs, 0, &res);
+  snprintf(admin_hostname, sizeof(admin_hostname), "%s.local.", DNSSDHostName);
+  httpAssembleURIf(HTTP_URI_CODING_ALL, adminurl_str, sizeof(adminurl_str),
+                   "http", NULL, admin_hostname, DNSSDPort, "/%s/%s",
+                  (p->type & CUPS_PRINTER_CLASS) ? "classes" : "printers",
+                  p->name);
+  keyvalue[i  ][0] = "adminurl";
+  keyvalue[i++][1] = adminurl_str;
 
- /*
-  * If ldap search was not successfull then exit function...
-  */
+  keyvalue[i  ][0] = "note";
+  keyvalue[i++][1] = p->location ? p->location : "";
 
-  if (rc != LDAP_SUCCESS && rc != LDAP_NO_SUCH_OBJECT)
-    return;
+  keyvalue[i  ][0] = "priority";
+  keyvalue[i++][1] = for_lpd ? "100" : "0";
 
- /*
-  * Check if we need to insert or update the LDAP entry...
-  */
+  keyvalue[i  ][0] = "product";
+  keyvalue[i++][1] = p->pc && p->pc->product ? p->pc->product : "Unknown";
 
-  if (ldap_count_entries(BrowseLDAPHandle, res) > 0 &&
-      rc != LDAP_NO_SUCH_OBJECT)
+  keyvalue[i  ][0] = "pdl";
+  keyvalue[i++][1] = p->pdl ? p->pdl : "application/postscript";
+
+  if (get_auth_info_required(p, air_str, sizeof(air_str)))
   {
-   /*
-    * Printserver has already been registered, check if
-    * modification is required...
-    */
+    keyvalue[i  ][0] = "air";
+    keyvalue[i++][1] = air_str;
+  }
 
-    e = ldap_first_entry(BrowseLDAPHandle, res);
+  keyvalue[i  ][0] = "UUID";
+  keyvalue[i++][1] = p->uuid + 9;
 
-   /*
-    * Get the required values from this entry...
-    */
+#ifdef HAVE_SSL
+  keyvalue[i  ][0] = "TLS";
+  keyvalue[i++][1] = "1.2";
+#endif /* HAVE_SSL */
 
-    if (ldap_getval_firststring(BrowseLDAPHandle, e, "description", old_desc,
-                                sizeof(old_desc)) == -1)
-      old_desc[0] = '\0';
+  keyvalue[i  ][0] = "Transparent";
+  keyvalue[i++][1] = "F";
 
-   /*
-    * Check if modification is required...
-    */
+  keyvalue[i  ][0] = "Binary";
+  keyvalue[i++][1] = "F";
 
-    if ( strcmp(desc[0], old_desc) == 0 )
-    {
-     /*
-      * LDAP entry for the printer exists.
-      * Printer has already been registered,
-      * no modifications required...
-      */
-      cupsdLogMessage(CUPSD_LOG_DEBUG2,
-                      "send_ldap_ou: No updates required for %s", ou);
-    }
-    else
-    {
+  keyvalue[i  ][0] = "Fax";
+  keyvalue[i++][1] = (p->type & CUPS_PRINTER_FAX) ? "T" : "F";
 
-      cupsdLogMessage(CUPSD_LOG_DEBUG2,
-                      "send_ldap_ou: Replace entry for %s", ou);
+  keyvalue[i  ][0] = "Color";
+  keyvalue[i++][1] = (p->type & CUPS_PRINTER_COLOR) ? "T" : "F";
 
-      for (i = 0; i < 3; i ++)
-      {
-        pmods[i]         = mods + i;
-        pmods[i]->mod_op = LDAP_MOD_REPLACE;
-      }
-      pmods[i] = NULL;
-
-#  if defined(HAVE_OPENLDAP) && LDAP_API_VERSION > 3000
-      if ((rcmod = ldap_modify_ext_s(BrowseLDAPHandle, dn, pmods, NULL,
-                                     NULL)) != LDAP_SUCCESS)
-#  else
-      if ((rcmod = ldap_modify_s(BrowseLDAPHandle, dn, pmods)) != LDAP_SUCCESS)
-#  endif /* defined(HAVE_OPENLDAP) && LDAP_API_VERSION > 3000 */
-      {
-        cupsdLogMessage(CUPSD_LOG_ERROR,
-                        "LDAP modify for %s failed with status %d: %s",
-                        ou, rcmod, ldap_err2string(rcmod));
-        if (rcmod == LDAP_SERVER_DOWN)
-          ldap_reconnect();
-      }
-    }
-  }
-  else
-  {
-   /*
-    * Printserver has never been registered,
-    * add registration...
-    */
+  keyvalue[i  ][0] = "Duplex";
+  keyvalue[i++][1] = (p->type & CUPS_PRINTER_DUPLEX) ? "T" : "F";
 
-    cupsdLogMessage(CUPSD_LOG_DEBUG2,
-                    "send_ldap_ou: Add entry for %s", ou);
+  keyvalue[i  ][0] = "Staple";
+  keyvalue[i++][1] = (p->type & CUPS_PRINTER_STAPLE) ? "T" : "F";
 
-    for (i = 0; i < 3; i ++)
-    {
-      pmods[i]         = mods + i;
-      pmods[i]->mod_op = LDAP_MOD_ADD;
-    }
-    pmods[i] = NULL;
-
-#  if defined(HAVE_OPENLDAP) && LDAP_API_VERSION > 3000
-    if ((rcmod = ldap_add_ext_s(BrowseLDAPHandle, dn, pmods, NULL,
-                                NULL)) != LDAP_SUCCESS)
-#  else
-    if ((rcmod = ldap_add_s(BrowseLDAPHandle, dn, pmods)) != LDAP_SUCCESS)
-#  endif /* defined(HAVE_OPENLDAP) && LDAP_API_VERSION > 3000 */
-    {
-      cupsdLogMessage(CUPSD_LOG_ERROR,
-                      "LDAP add for %s failed with status %d: %s",
-                      ou, rcmod, ldap_err2string(rcmod));
-      if (rcmod == LDAP_SERVER_DOWN)
-        ldap_reconnect();
-    }
-  }
+  keyvalue[i  ][0] = "Copies";
+  keyvalue[i++][1] = (p->type & CUPS_PRINTER_COPIES) ? "T" : "F";
 
-  if (rc == LDAP_SUCCESS)
-    ldap_freeres(res);
-}
+  keyvalue[i  ][0] = "Collate";
+  keyvalue[i++][1] = (p->type & CUPS_PRINTER_COLLATE) ? "T" : "F";
 
+  keyvalue[i  ][0] = "Punch";
+  keyvalue[i++][1] = (p->type & CUPS_PRINTER_PUNCH) ? "T" : "F";
 
-/*
- * 'send_ldap_browse()' - Send LDAP printer registrations.
- */
+  keyvalue[i  ][0] = "Bind";
+  keyvalue[i++][1] = (p->type & CUPS_PRINTER_BIND) ? "T" : "F";
 
-static void
-send_ldap_browse(cupsd_printer_t *p)   /* I - Printer to register */
-{
-  int          i;                      /* Looping var... */
-  LDAPMod      mods[7];                /* The 7 attributes we will be adding */
-  LDAPMod      *pmods[8];              /* Pointers to the 7 attributes + NULL */
-  LDAPMessage  *res,                   /* Search result token */
-               *e;                     /* Current entry from search */
-  char         *cn_value[2],           /* Change records */
-               *uri[2],
-               *info[2],
-               *location[2],
-               *make_model[2],
-               *type[2],
-               typestring[255],        /* String to hold printer-type */
-               dn[1024];               /* DN of the printer we are adding */
-  int          rc;                     /* LDAP status */
-  int          rcmod;                  /* LDAP status for modifications */
-  char         old_uri[HTTP_MAX_URI],  /* Printer URI */
-               old_location[1024],     /* Printer location */
-               old_info[1024],         /* Printer information */
-               old_make_model[1024],   /* Printer make and model */
-               old_type_string[30];    /* Temporary type number */
-  int          old_type;               /* Printer type */
-  static const char * const objectClass_values[] =
-               {                       /* The 3 objectClass's we use in */
-                 "top",                /* our LDAP entries              */
-                 "device",
-                 "cupsPrinter",
-                 NULL
-               };
-
-
-  cupsdLogMessage(CUPSD_LOG_DEBUG2, "send_ldap_browse: %s", p->name);
+  keyvalue[i  ][0] = "Sort";
+  keyvalue[i++][1] = (p->type & CUPS_PRINTER_SORT) ? "T" : "F";
 
- /*
-  * Exit function if LDAP updates has been disabled...
-  */
+  keyvalue[i  ][0] = "Scan";
+  keyvalue[i++][1] = (p->type & CUPS_PRINTER_MFP) ? "T" : "F";
 
-  if (!BrowseLDAPUpdate)
-  {
-    cupsdLogMessage(CUPSD_LOG_DEBUG2,
-                    "send_ldap_browse: Updates temporary disabled; "
-                   "skipping...");
-    return;
-  }
+  snprintf(type_str, sizeof(type_str), "0x%X", p->type | CUPS_PRINTER_REMOTE);
+  snprintf(state_str, sizeof(state_str), "%d", p->state);
 
- /*
-  * Reconnect if LDAP Handle is invalid...
-  */
+  keyvalue[i  ][0] = "printer-state";
+  keyvalue[i++][1] = state_str;
 
-  if (!BrowseLDAPHandle)
-  {
-    cupsdLogMessage(CUPSD_LOG_DEBUG2,
-                    "send_ldap_browse: LDAP Handle is invalid. Try "
-                   "reconnecting...");
-    ldap_reconnect();
-    return;
-  }
+  keyvalue[i  ][0] = "printer-type";
+  keyvalue[i++][1] = type_str;
 
  /*
-  * Everything in ldap is ** so we fudge around it...
+  * Then pack them into a proper txt record...
   */
 
-  sprintf(typestring, "%u", p->type);
-
-  cn_value[0]   = p->name;
-  cn_value[1]   = NULL;
-  info[0]       = p->info ? p->info : "Unknown";
-  info[1]       = NULL;
-  location[0]   = p->location ? p->location : "Unknown";
-  location[1]   = NULL;
-  make_model[0] = p->make_model ? p->make_model : "Unknown";
-  make_model[1] = NULL;
-  type[0]       = typestring;
-  type[1]       = NULL;
-  uri[0]        = p->uri;
-  uri[1]        = NULL;
+  return (dnssdPackTxtRecord(txt_len, keyvalue, i));
+}
 
- /*
-  * Get ldap entry for printer ...
-  */
 
-  snprintf(dn, sizeof(dn), "cn=%s, ou=%s, %s", p->name, ServerName,
-           BrowseLDAPDN);
-  cupsdLogMessage(CUPSD_LOG_DEBUG2, "send_ldap_browse: dn=\"%s\"", dn);
+/*
+ * 'dnssdDeregisterPrinter()' - Stop sending broadcast information for a
+ *                              printer.
+ */
 
-  rc = ldap_search_rec(BrowseLDAPHandle, dn, LDAP_SCOPE_BASE, NULL,
-                       (char **)ldap_attrs, 0, &res);
+static void
+dnssdDeregisterPrinter(
+    cupsd_printer_t *p)                        /* I - Printer */
+{
+  cupsdLogMessage(CUPSD_LOG_DEBUG2, "dnssdDeregisterPrinter(%s)", p->name);
 
  /*
-  * If ldap search was not successfull then exit function
-  * and temporary disable LDAP updates...
+  * Closing the socket deregisters the service
   */
 
-  if (rc != LDAP_SUCCESS && rc != LDAP_NO_SUCH_OBJECT)
+  if (p->ipp_ref)
   {
-    if (BrowseLDAPUpdate &&
-        (rc == LDAP_SERVER_DOWN || rc == LDAP_CONNECT_ERROR))
-    {
-      BrowseLDAPUpdate = FALSE;
-      cupsdLogMessage(CUPSD_LOG_INFO,
-                      "LDAP update temporary disabled");
-    }
-
-    return;
+    DNSServiceRefDeallocate(p->ipp_ref);
+    p->ipp_ref = NULL;
   }
 
- /*
-  * Fill modification array...
-  */
-
-  mods[0].mod_type   = "cn";
-  mods[0].mod_values = cn_value;
-  mods[1].mod_type   = "printerDescription";
-  mods[1].mod_values = info;
-  mods[2].mod_type   = "printerURI";
-  mods[2].mod_values = uri;
-  mods[3].mod_type   = "printerLocation";
-  mods[3].mod_values = location;
-  mods[4].mod_type   = "printerMakeAndModel";
-  mods[4].mod_values = make_model;
-  mods[5].mod_type   = "printerType";
-  mods[5].mod_values = type;
-  mods[6].mod_type   = "objectClass";
-  mods[6].mod_values = (char **)objectClass_values;
-
- /*
-  * Check if we need to insert or update the LDAP entry...
-  */
-
-  if (ldap_count_entries(BrowseLDAPHandle, res) > 0 &&
-      rc != LDAP_NO_SUCH_OBJECT)
+  if (p->ipp_txt)
   {
    /*
-    * Printer has already been registered, check if
-    * modification is required...
-    */
-
-    e = ldap_first_entry(BrowseLDAPHandle, res);
-
-   /*
-    * Get the required values from this entry...
-    */
-
-    if (ldap_getval_firststring(BrowseLDAPHandle, e, "printerDescription",
-                                old_info, sizeof(old_info)) == -1)
-      old_info[0] = '\0';
-
-    if (ldap_getval_firststring(BrowseLDAPHandle, e, "printerLocation",
-                                old_location, sizeof(old_location)) == -1)
-      old_info[0] = '\0';
-
-    if (ldap_getval_firststring(BrowseLDAPHandle, e, "printerMakeAndModel",
-                                old_make_model, sizeof(old_make_model)) == -1)
-      old_info[0] = '\0';
-
-    if (ldap_getval_firststring(BrowseLDAPHandle, e, "printerType",
-                                old_type_string, sizeof(old_type_string)) == -1)
-      old_info[0] = '\0';
-
-    old_type = atoi(old_type_string);
-
-    if (ldap_getval_firststring(BrowseLDAPHandle, e, "printerURI", old_uri,
-                                sizeof(old_uri)) == -1)
-      old_info[0] = '\0';
-
-   /*
-    * Check if modification is required...
+    * p->ipp_txt is malloc'd, not _cupsStrAlloc'd...
     */
 
-    if (!strcmp(info[0], old_info) && !strcmp(uri[0], old_uri) &&
-        !strcmp(location[0], old_location) &&
-       !strcmp(make_model[0], old_make_model) && p->type == old_type)
-    {
-     /*
-      * LDAP entry for the printer exists. Printer has already been registered,
-      * no modifications required...
-      */
-
-      cupsdLogMessage(CUPSD_LOG_DEBUG2,
-                       "send_ldap_browse: No updates required for %s", p->name);
-    }
-    else
-    {
-     /*
-      * LDAP entry for the printer exists.  Printer has already been registered,
-      * modify the current registration...
-      */
-
-      cupsdLogMessage(CUPSD_LOG_DEBUG2,
-                      "send_ldap_browse: Replace entry for %s", p->name);
+    free(p->ipp_txt);
+    p->ipp_txt = NULL;
+  }
 
-      for (i = 0; i < 7; i ++)
-      {
-        pmods[i]         = mods + i;
-        pmods[i]->mod_op = LDAP_MOD_REPLACE;
-      }
-      pmods[i] = NULL;
-
-#  if defined(HAVE_OPENLDAP) && LDAP_API_VERSION > 3000
-      if ((rcmod = ldap_modify_ext_s(BrowseLDAPHandle, dn, pmods, NULL,
-                                     NULL)) != LDAP_SUCCESS)
-#  else
-      if ((rcmod = ldap_modify_s(BrowseLDAPHandle, dn, pmods)) != LDAP_SUCCESS)
-#  endif /* defined(HAVE_OPENLDAP) && LDAP_API_VERSION > 3000 */
-      {
-        cupsdLogMessage(CUPSD_LOG_ERROR,
-                        "LDAP modify for %s failed with status %d: %s",
-                        p->name, rcmod, ldap_err2string(rcmod));
-        if (rcmod == LDAP_SERVER_DOWN)
-          ldap_reconnect();
-      }
-    }
+  if (p->printer_ref)
+  {
+    DNSServiceRefDeallocate(p->printer_ref);
+    p->printer_ref = NULL;
   }
-  else
+
+  if (p->printer_txt)
   {
    /*
-    * No LDAP entry exists for the printer.  Printer has never been registered,
-    * add the current registration...
+    * p->printer_txt is malloc'd, not _cupsStrAlloc'd...
     */
 
-    send_ldap_ou(ServerName, BrowseLDAPDN, "CUPS Server");
-
-    cupsdLogMessage(CUPSD_LOG_DEBUG2,
-                    "send_ldap_browse: Add entry for %s", p->name);
-
-    for (i = 0; i < 7; i ++)
-    {
-      pmods[i]         = mods + i;
-      pmods[i]->mod_op = LDAP_MOD_ADD;
-    }
-    pmods[i] = NULL;
-
-#  if defined(HAVE_OPENLDAP) && LDAP_API_VERSION > 3000
-    if ((rcmod = ldap_add_ext_s(BrowseLDAPHandle, dn, pmods, NULL,
-                                NULL)) != LDAP_SUCCESS)
-#  else
-    if ((rcmod = ldap_add_s(BrowseLDAPHandle, dn, pmods)) != LDAP_SUCCESS)
-#  endif /* defined(HAVE_OPENLDAP) && LDAP_API_VERSION > 3000 */
-    {
-      cupsdLogMessage(CUPSD_LOG_ERROR,
-                      "LDAP add for %s failed with status %d: %s",
-                      p->name, rcmod, ldap_err2string(rcmod));
-      if (rcmod == LDAP_SERVER_DOWN)
-        ldap_reconnect();
-    }
+    free(p->printer_txt);
+    p->printer_txt = NULL;
   }
 
-  if (rc == LDAP_SUCCESS)
-    ldap_freeres(res);
+ /*
+  * Remove the printer from the array of DNS-SD printers, then clear the
+  * registered name...
+  */
+
+  cupsArrayRemove(DNSSDPrinters, p);
+  cupsdClearString(&p->reg_name);
 }
 
 
 /*
- * 'ldap_dereg_printer()' - Delete printer from directory
+ * 'dnssdPackTxtRecord()' - Pack an array of key/value pairs into the
+ *                          TXT record format.
  */
 
-static void
-ldap_dereg_printer(cupsd_printer_t *p) /* I - Printer to deregister */
+static char *                          /* O - TXT record */
+dnssdPackTxtRecord(int  *txt_len,      /* O - TXT record length */
+                  char *keyvalue[][2], /* I - Table of key value pairs */
+                  int  count)          /* I - Items in table */
 {
-  char         dn[1024];               /* DN of the printer */
-  int          rc;                     /* LDAP status */
-
+  int  i;                              /* Looping var */
+  int  length;                         /* Length of TXT record */
+  int  length2;                                /* Length of value */
+  char *txtRecord;                     /* TXT record buffer */
+  char *cursor;                                /* Looping pointer */
 
-  cupsdLogMessage(CUPSD_LOG_DEBUG2, "ldap_dereg_printer: Remove entry for %s",
-                  p->name);
 
  /*
-  * Reconnect if LDAP Handle is invalid...
+  * Calculate the buffer size
   */
 
-  if (!BrowseLDAPHandle)
-  {
-    ldap_reconnect();
-    return;
-  }
+  if (count <= 0)
+    return (NULL);
+
+  for (length = i = 0; i < count; i++)
+    length += 1 + strlen(keyvalue[i][0]) +
+             (keyvalue[i][1] ? 1 + strlen(keyvalue[i][1]) : 0);
 
  /*
-  * Get dn for printer and delete LDAP entry...
+  * Allocate and fill it
   */
 
-  snprintf(dn, sizeof(dn), "cn=%s, ou=%s, %s", p->name, ServerName,
-           BrowseLDAPDN);
-  cupsdLogMessage(CUPSD_LOG_DEBUG2, "ldap_dereg_printer: dn=\"%s\"", dn);
-
-#  if defined(HAVE_OPENLDAP) && LDAP_API_VERSION > 3000
-  if ((rc = ldap_delete_ext_s(BrowseLDAPHandle, dn, NULL,
-                              NULL)) != LDAP_SUCCESS)
-#  else
-  if ((rc = ldap_delete_s(BrowseLDAPHandle, dn)) != LDAP_SUCCESS)
-#  endif /* defined(HAVE_OPENLDAP) && LDAP_API_VERSION > 3000 */
+  txtRecord = malloc(length);
+  if (txtRecord)
   {
-    cupsdLogMessage(CUPSD_LOG_WARN,
-                    "LDAP delete for %s failed with status %d: %s",
-                    p->name, rc, ldap_err2string(rc));
+    *txt_len = length;
 
-   /*
-    * If we had a connection problem (connection timed out, etc.)
-    * we should reconnect and try again to delete the entry...
-    */
+    for (cursor = txtRecord, i = 0; i < count; i++)
+    {
+     /*
+      * Drop in the p-string style length byte followed by the data
+      */
+
+      length  = strlen(keyvalue[i][0]);
+      length2 = keyvalue[i][1] ? 1 + strlen(keyvalue[i][1]) : 0;
+
+      *cursor++ = (unsigned char)(length + length2);
+
+      memcpy(cursor, keyvalue[i][0], length);
+      cursor += length;
 
-    if (rc == LDAP_SERVER_DOWN || rc == LDAP_CONNECT_ERROR)
-    {
-      cupsdLogMessage(CUPSD_LOG_INFO,
-                      "Retry deleting LDAP entry for %s after a reconnect...", p->name);
-      ldap_reconnect();
-
-#  if defined(HAVE_OPENLDAP) && LDAP_API_VERSION > 3000
-      if ((rc = ldap_delete_ext_s(BrowseLDAPHandle, dn, NULL,
-                                  NULL)) != LDAP_SUCCESS)
-#  else
-      if ((rc = ldap_delete_s(BrowseLDAPHandle, dn)) != LDAP_SUCCESS)
-#  endif /* defined(HAVE_OPENLDAP) && LDAP_API_VERSION > 3000 */
-        cupsdLogMessage(CUPSD_LOG_WARN,
-                        "LDAP delete for %s failed with status %d: %s",
-                        p->name, rc, ldap_err2string(rc));
+      if (length2)
+      {
+        length2 --;
+       *cursor++ = '=';
+       memcpy(cursor, keyvalue[i][1], length2);
+       cursor += length2;
+      }
     }
   }
+
+  return (txtRecord);
 }
 
 
 /*
- * 'ldap_dereg_ou()' - Remove the organizational unit.
+ * 'dnssdRegisterCallback()' - DNSServiceRegister callback.
  */
 
 static void
-ldap_dereg_ou(char *ou,                        /* I - Organizational unit (servername) */
-              char *basedn)            /* I - Dase dn */
+dnssdRegisterCallback(
+    DNSServiceRef      sdRef,          /* I - DNS Service reference */
+    DNSServiceFlags    flags,          /* I - Reserved for future use */
+    DNSServiceErrorType        errorCode,      /* I - Error code */
+    const char         *name,          /* I - Service name */
+    const char         *regtype,       /* I - Service type */
+    const char         *domain,        /* I - Domain. ".local" for now */
+    void               *context)       /* I - User-defined context */
 {
-  char         dn[1024];               /* DN of the printer */
-  int          rc;                     /* LDAP status */
+  cupsd_printer_t *p = (cupsd_printer_t *)context;
+                                       /* Current printer */
 
 
-  cupsdLogMessage(CUPSD_LOG_DEBUG2, "ldap_dereg_ou: Remove entry for %s", ou);
+  (void)sdRef;
+  (void)flags;
+  (void)domain;
 
- /*
-  * Reconnect if LDAP Handle is invalid...
-  */
+  cupsdLogMessage(CUPSD_LOG_DEBUG2, "dnssdRegisterCallback(%s, %s) for %s (%s)",
+                  name, regtype, p ? p->name : "Web Interface",
+                 p ? (p->reg_name ? p->reg_name : "(null)") : "NA");
 
-  if (!BrowseLDAPHandle)
+  if (errorCode)
   {
-    ldap_reconnect();
+    cupsdLogMessage(CUPSD_LOG_ERROR,
+                   "DNSServiceRegister failed with error %d", (int)errorCode);
     return;
   }
-
- /*
-  * Get dn for printer and delete LDAP entry...
-  */
-
-  snprintf(dn, sizeof(dn), "ou=%s, %s", ou, basedn);
-  cupsdLogMessage(CUPSD_LOG_DEBUG2, "ldap_dereg_ou: dn=\"%s\"", dn);
-
-#  if defined(HAVE_OPENLDAP) && LDAP_API_VERSION > 3000
-  if ((rc = ldap_delete_ext_s(BrowseLDAPHandle, dn, NULL,
-                              NULL)) != LDAP_SUCCESS)
-#  else
-  if ((rc = ldap_delete_s(BrowseLDAPHandle, dn)) != LDAP_SUCCESS)
-#  endif /* defined(HAVE_OPENLDAP) && LDAP_API_VERSION > 3000 */
+  else if (p && (!p->reg_name || _cups_strcasecmp(name, p->reg_name)))
   {
-    cupsdLogMessage(CUPSD_LOG_WARN,
-                    "LDAP delete for %s failed with status %d: %s",
-                    ou, rc, ldap_err2string(rc));
+    cupsdLogMessage(CUPSD_LOG_INFO, "Using service name \"%s\" for \"%s\"",
+                    name, p->name);
 
-   /*
-    * If we had a connection problem (connection timed out, etc.)
-    * we should reconnect and try again to delete the entry...
-    */
+    cupsArrayRemove(DNSSDPrinters, p);
+    cupsdSetString(&p->reg_name, name);
+    cupsArrayAdd(DNSSDPrinters, p);
 
-    if (rc == LDAP_SERVER_DOWN || rc == LDAP_CONNECT_ERROR)
-    {
-      cupsdLogMessage(CUPSD_LOG_INFO,
-                      "Retry deleting LDAP entry for %s after a reconnect...", ou);
-      ldap_reconnect();
-#  if defined(HAVE_OPENLDAP) && LDAP_API_VERSION > 3000
-      if ((rc = ldap_delete_ext_s(BrowseLDAPHandle, dn, NULL,
-                                  NULL)) != LDAP_SUCCESS)
-#  else
-      if ((rc = ldap_delete_s(BrowseLDAPHandle, dn)) != LDAP_SUCCESS)
-#  endif /* defined(HAVE_OPENLDAP) && LDAP_API_VERSION > 3000 */
-        cupsdLogMessage(CUPSD_LOG_WARN,
-                        "LDAP delete for %s failed with status %d: %s",
-                        ou, rc, ldap_err2string(rc));
-    }
+    LastEvent |= CUPSD_EVENT_PRINTER_MODIFIED;
   }
 }
-#endif /* HAVE_LDAP */
 
 
-#ifdef HAVE_LIBSLP
 /*
- * 'send_slp_browse()' - Register the specified printer with SLP.
+ * 'dnssdRegisterPrinter()' - Start sending broadcast information for a printer
+ *                           or update the broadcast contents.
  */
 
 static void
-send_slp_browse(cupsd_printer_t *p)    /* I - Printer to register */
+dnssdRegisterPrinter(cupsd_printer_t *p)/* I - Printer */
 {
-  char         srvurl[HTTP_MAX_URI],   /* Printer service URI */
-               attrs[8192],            /* Printer attributes */
-               finishings[1024],       /* Finishings to support */
-               make_model[IPP_MAX_NAME * 2],
-                                       /* Make and model, quoted */
-               location[IPP_MAX_NAME * 2],
-                                       /* Location, quoted */
-               info[IPP_MAX_NAME * 2], /* Info, quoted */
-               *src,                   /* Pointer to original string */
-               *dst;                   /* Pointer to destination string */
-  ipp_attribute_t *authentication;     /* uri-authentication-supported value */
-  SLPError     error;                  /* SLP error, if any */
-
-
-  cupsdLogMessage(CUPSD_LOG_DEBUG, "send_slp_browse(%p = \"%s\")", p,
-                  p->name);
-
- /*
-  * Make the SLP service URL that conforms to the IANA
-  * 'printer:' template.
-  */
+  DNSServiceErrorType  se;             /* dnssd errors */
+  char                 *ipp_txt,       /* IPP TXT record buffer */
+                       *printer_txt,   /* LPD TXT record buffer */
+                       name[1024],     /* Service name */
+                       *nameptr;       /* Pointer into name */
+  int                  ipp_len,        /* IPP TXT record length */
+                       printer_len,    /* LPD TXT record length */
+                       printer_port;   /* LPD port number */
+  const char           *regtype;       /* Registration type */
 
-  snprintf(srvurl, sizeof(srvurl), SLP_CUPS_SRVTYPE ":%s", p->uri);
 
-  cupsdLogMessage(CUPSD_LOG_DEBUG2, "Service URL = \"%s\"", srvurl);
+  cupsdLogMessage(CUPSD_LOG_DEBUG2, "dnssdRegisterPrinter(%s) %s", p->name,
+                  !p->ipp_ref ? "new" : "update");
 
  /*
-  * Figure out the finishings string...
+  * If per-printer sharing was just disabled make sure we're not
+  * registered before returning.
   */
 
-  if (p->type & CUPS_PRINTER_STAPLE)
-    strcpy(finishings, "staple");
-  else
-    finishings[0] = '\0';
-
-  if (p->type & CUPS_PRINTER_BIND)
-  {
-    if (finishings[0])
-      strlcat(finishings, ",bind", sizeof(finishings));
-    else
-      strcpy(finishings, "bind");
-  }
-
-  if (p->type & CUPS_PRINTER_PUNCH)
+  if (!p->shared)
   {
-    if (finishings[0])
-      strlcat(finishings, ",punch", sizeof(finishings));
-    else
-      strcpy(finishings, "punch");
+    dnssdDeregisterPrinter(p);
+    return;
   }
 
-  if (p->type & CUPS_PRINTER_COVER)
-  {
-    if (finishings[0])
-      strlcat(finishings, ",cover", sizeof(finishings));
-    else
-      strcpy(finishings, "cover");
-  }
+ /*
+  * The registered name takes the form of "<printer-info> @ <computer name>"...
+  */
 
-  if (p->type & CUPS_PRINTER_SORT)
+  if (p->info && strlen(p->info) > 0)
   {
-    if (finishings[0])
-      strlcat(finishings, ",sort", sizeof(finishings));
+    if (DNSSDComputerName)
+      snprintf(name, sizeof(name), "%s @ %s", p->info, DNSSDComputerName);
     else
-      strcpy(finishings, "sort");
+      strlcpy(name, p->info, sizeof(name));
   }
-
-  if (!finishings[0])
-    strcpy(finishings, "none");
+  else if (DNSSDComputerName)
+    snprintf(name, sizeof(name), "%s @ %s", p->name, DNSSDComputerName);
+  else
+    strlcpy(name, p->name, sizeof(name));
 
  /*
-  * Quote any commas in the make and model, location, and info strings...
+  * If an existing printer was renamed, unregister it and start over...
   */
 
-  for (src = p->make_model, dst = make_model;
-       src && *src && dst < (make_model + sizeof(make_model) - 2);)
-  {
-    if (*src == ',' || *src == '\\' || *src == ')')
-      *dst++ = '\\';
-
-    *dst++ = *src++;
-  }
-
-  *dst = '\0';
-
-  if (!make_model[0])
-    strcpy(make_model, "Unknown");
-
-  for (src = p->location, dst = location;
-       src && *src && dst < (location + sizeof(location) - 2);)
-  {
-    if (*src == ',' || *src == '\\' || *src == ')')
-      *dst++ = '\\';
-
-    *dst++ = *src++;
-  }
-
-  *dst = '\0';
-
-  if (!location[0])
-    strcpy(location, "Unknown");
+  if (p->reg_name && strcmp(p->reg_name, name))
+    dnssdDeregisterPrinter(p);
 
-  for (src = p->info, dst = info;
-       src && *src && dst < (info + sizeof(info) - 2);)
+  if (!p->reg_name)
   {
-    if (*src == ',' || *src == '\\' || *src == ')')
-      *dst++ = '\\';
-
-    *dst++ = *src++;
+    cupsdSetString(&p->reg_name, name);
+    cupsArrayAdd(DNSSDPrinters, p);
   }
 
-  *dst = '\0';
-
-  if (!info[0])
-    strcpy(info, "Unknown");
-
- /*
-  * Get the authentication value...
-  */
-
-  authentication = ippFindAttribute(p->attrs, "uri-authentication-supported",
-                                    IPP_TAG_KEYWORD);
-
- /*
-  * Make the SLP attribute string list that conforms to
-  * the IANA 'printer:' template.
-  */
-
-  snprintf(attrs, sizeof(attrs),
-           "(printer-uri-supported=%s),"
-           "(uri-authentication-supported=%s>),"
-#ifdef HAVE_SSL
-           "(uri-security-supported=tls>),"
-#else
-           "(uri-security-supported=none>),"
-#endif /* HAVE_SSL */
-           "(printer-name=%s),"
-           "(printer-location=%s),"
-           "(printer-info=%s),"
-           "(printer-more-info=%s),"
-           "(printer-make-and-model=%s),"
-          "(printer-type=%d),"
-          "(charset-supported=utf-8),"
-          "(natural-language-configured=%s),"
-          "(natural-language-supported=de,en,es,fr,it),"
-           "(color-supported=%s),"
-           "(finishings-supported=%s),"
-           "(sides-supported=one-sided%s),"
-          "(multiple-document-jobs-supported=true)"
-          "(ipp-versions-supported=1.0,1.1)",
-          p->uri, authentication->values[0].string.text, p->name, location,
-          info, p->uri, make_model, p->type, DefaultLanguage,
-           p->type & CUPS_PRINTER_COLOR ? "true" : "false",
-           finishings,
-           p->type & CUPS_PRINTER_DUPLEX ?
-              ",two-sided-long-edge,two-sided-short-edge" : "");
-
-  cupsdLogMessage(CUPSD_LOG_DEBUG2, "Attributes = \"%s\"", attrs);
-
  /*
-  * Register the printer with the SLP server...
+  * Register IPP and (optionally) LPD...
   */
 
-  error = SLPReg(BrowseSLPHandle, srvurl, BrowseTimeout,
-                SLP_CUPS_SRVTYPE, attrs, SLP_TRUE, slp_reg_callback, 0);
-
-  if (error != SLP_OK)
-    cupsdLogMessage(CUPSD_LOG_ERROR, "SLPReg of \"%s\" failed with status %d!", p->name,
-                    error);
-}
-
+  ipp_len = 0;                         /* anti-compiler-warning-code */
+  ipp_txt = dnssdBuildTxtRecord(&ipp_len, p, 0);
 
-/*
- * 'slp_attr_callback()' - SLP attribute callback
- */
+  if (p->ipp_ref &&
+      (ipp_len != p->ipp_len || memcmp(ipp_txt, p->ipp_txt, ipp_len)))
+  {
+   /*
+    * Update the existing registration...
+    */
 
-static SLPBoolean                      /* O - SLP_TRUE for success */
-slp_attr_callback(
-    SLPHandle  hslp,                   /* I - SLP handle */
-    const char *attrlist,              /* I - Attribute list */
-    SLPError   errcode,                        /* I - Parsing status for this attr */
-    void       *cookie)                        /* I - Current printer */
-{
-  char                 *tmp = 0;       /* Temporary string */
-  cupsd_printer_t      *p = (cupsd_printer_t*)cookie;
-                                       /* Current printer */
+    /* A TTL of 0 means use record's original value (Radar 3176248) */
+    if ((se = DNSServiceUpdateRecord(p->ipp_ref, NULL, 0, ipp_len, ipp_txt,
+                                    0)) == kDNSServiceErr_NoError)
+    {
+      if (p->ipp_txt)
+       free(p->ipp_txt);
 
+      p->ipp_txt = ipp_txt;
+      p->ipp_len = ipp_len;
+      ipp_txt    = NULL;
+    }
+    else
+    {
+     /*
+      * Failed to update record, lets close this reference and move on...
+      */
 
-  (void)hslp;                          /* anti-compiler-warning-code */
+      cupsdLogMessage(CUPSD_LOG_ERROR,
+                     "Unable to update IPP DNS-SD record for %s - %d", p->name,
+                     se);
 
- /*
-  * Bail if there was an error
-  */
+      DNSServiceRefDeallocate(p->ipp_ref);
+      p->ipp_ref = NULL;
+    }
+  }
 
-  if (errcode != SLP_OK)
-    return (SLP_TRUE);
+  if (!p->ipp_ref)
+  {
+   /*
+    * Initial registration.  Use the _fax-ipp regtype for fax queues...
+    */
 
- /*
-  * Parse the attrlist to obtain things needed to build CUPS browse packet
-  */
+    regtype = (p->type & CUPS_PRINTER_FAX) ? "_fax-ipp._tcp" : DNSSDRegType;
 
-  memset(p, 0, sizeof(cupsd_printer_t));
+    cupsdLogMessage(CUPSD_LOG_DEBUG,
+                   "Registering DNS-SD printer %s with name \"%s\" and "
+                   "type \"%s\"", p->name, name, regtype);
 
-  if (slp_get_attr(attrlist, "(printer-location=", &(p->location)))
-    return (SLP_FALSE);
-  if (slp_get_attr(attrlist, "(printer-info=", &(p->info)))
-    return (SLP_FALSE);
-  if (slp_get_attr(attrlist, "(printer-make-and-model=", &(p->make_model)))
-    return (SLP_FALSE);
-  if (!slp_get_attr(attrlist, "(printer-type=", &tmp))
-    p->type = atoi(tmp);
-  else
-    p->type = CUPS_PRINTER_REMOTE;
+   /*
+    * Register the queue, dropping characters as needed until we succeed...
+    */
 
-  cupsdClearString(&tmp);
+    nameptr = name + strlen(name);
 
-  return (SLP_TRUE);
-}
+    do
+    {
+      p->ipp_ref = DNSSDRef;
+      if ((se = DNSServiceRegister(&p->ipp_ref, kDNSServiceFlagsShareConnection,
+                                   0, name, regtype, NULL, NULL,
+                                  htons(DNSSDPort), ipp_len, ipp_txt,
+                                  dnssdRegisterCallback,
+                                  p)) == kDNSServiceErr_BadParam)
+      {
+       /*
+        * Name is too long, drop trailing characters, taking into account
+       * UTF-8 encoding...
+       */
 
+        nameptr --;
 
-/*
- * 'slp_dereg_printer()' - SLPDereg() the specified printer
- */
+        while (nameptr > name && (*nameptr & 0xc0) == 0x80)
+         nameptr --;
 
-static void
-slp_dereg_printer(cupsd_printer_t *p)  /* I - Printer */
-{
-  char srvurl[HTTP_MAX_URI];           /* Printer service URI */
+        if (nameptr > name)
+          *nameptr = '\0';
+      }
+    }
+    while (se == kDNSServiceErr_BadParam && nameptr > name);
 
+    if (se == kDNSServiceErr_NoError)
+    {
+      p->ipp_txt = ipp_txt;
+      p->ipp_len = ipp_len;
+      ipp_txt    = NULL;
+    }
+    else
+      cupsdLogMessage(CUPSD_LOG_WARN,
+                      "DNS-SD IPP registration of \"%s\" failed: %d",
+                     p->name, se);
+  }
 
-  cupsdLogMessage(CUPSD_LOG_DEBUG, "slp_dereg_printer: printer=\"%s\"", p->name);
+  if (ipp_txt)
+    free(ipp_txt);
 
-  if (!(p->type & CUPS_PRINTER_REMOTE))
+  if (BrowseLocalProtocols & BROWSE_LPD)
   {
-   /*
-    * Make the SLP service URL that conforms to the IANA
-    * 'printer:' template.
-    */
-
-    snprintf(srvurl, sizeof(srvurl), SLP_CUPS_SRVTYPE ":%s", p->uri);
+    printer_len  = 0;                  /* anti-compiler-warning-code */
+    printer_port = 515;
+    printer_txt  = dnssdBuildTxtRecord(&printer_len, p, 1);
+  }
+  else
+  {
+    printer_len  = 0;
+    printer_port = 0;
+    printer_txt  = NULL;
+  }
 
+  if (p->printer_ref &&
+      (printer_len != p->printer_len ||
+       memcmp(printer_txt, p->printer_txt, printer_len)))
+  {
    /*
-    * Deregister the printer...
+    * Update the existing registration...
     */
 
-    SLPDereg(BrowseSLPHandle, srvurl, slp_reg_callback, 0);
-  }
-}
-
-
-/*
- * 'slp_get_attr()' - Get an attribute from an SLP registration.
- */
-
-static int                             /* O - 0 on success */
-slp_get_attr(const char *attrlist,     /* I - Attribute list string */
-             const char *tag,          /* I - Name of attribute */
-             char       **valbuf)      /* O - Value */
-{
-  char *ptr1,                          /* Pointer into string */
-       *ptr2;                          /* ... */
-
-
-  cupsdClearString(valbuf);
-
-  if ((ptr1 = strstr(attrlist, tag)) != NULL)
-  {
-    ptr1 += strlen(tag);
+    /* A TTL of 0 means use record's original value (Radar 3176248) */
+    if ((se = DNSServiceUpdateRecord(p->printer_ref, NULL, 0, printer_len,
+                                    printer_txt,
+                                    0)) == kDNSServiceErr_NoError)
+    {
+      if (p->printer_txt)
+       free(p->printer_txt);
 
-    if ((ptr2 = strchr(ptr1,')')) != NULL)
+      p->printer_txt = printer_txt;
+      p->printer_len = printer_len;
+      printer_txt    = NULL;
+    }
+    else
     {
      /*
-      * Copy the value...
-      */
-
-      *valbuf = calloc(ptr2 - ptr1 + 1, 1);
-      strncpy(*valbuf, ptr1, ptr2 - ptr1);
-
-     /*
-      * Dequote the value...
+      * Failed to update record, lets close this reference and move on...
       */
 
-      for (ptr1 = *valbuf; *ptr1; ptr1 ++)
-       if (*ptr1 == '\\' && ptr1[1])
-         _cups_strcpy(ptr1, ptr1 + 1);
+      cupsdLogMessage(CUPSD_LOG_ERROR,
+                     "Unable to update LPD DNS-SD record for %s - %d",
+                     p->name, se);
 
-      return (0);
+      DNSServiceRefDeallocate(p->printer_ref);
+      p->printer_ref = NULL;
     }
   }
 
-  return (-1);
-}
-
+  if (!p->printer_ref)
+  {
+   /*
+    * Initial registration...
+    */
 
-/*
- * 'slp_reg_callback()' - Empty SLPRegReport.
- */
+    cupsdLogMessage(CUPSD_LOG_DEBUG,
+                   "Registering DNS-SD printer %s with name \"%s\" and "
+                   "type \"_printer._tcp\"", p->name, name);
 
-static void
-slp_reg_callback(SLPHandle hslp,       /* I - SLP handle */
-                 SLPError  errcode,    /* I - Error code, if any */
-                void      *cookie)     /* I - App data */
-{
-  (void)hslp;
-  (void)errcode;
-  (void)cookie;
+    p->printer_ref = DNSSDRef;
+    if ((se = DNSServiceRegister(&p->printer_ref,
+                                kDNSServiceFlagsShareConnection,
+                                0, name, "_printer._tcp", NULL, NULL,
+                                htons(printer_port), printer_len, printer_txt,
+                                dnssdRegisterCallback,
+                                p)) == kDNSServiceErr_NoError)
+    {
+      p->printer_txt = printer_txt;
+      p->printer_len = printer_len;
+      printer_txt    = NULL;
+    }
+    else
+      cupsdLogMessage(CUPSD_LOG_WARN,
+                     "DNS-SD LPD registration of \"%s\" failed: %d",
+                     p->name, se);
+  }
 
-  return;
+  if (printer_txt)
+    free(printer_txt);
 }
 
 
 /*
- * 'slp_url_callback()' - SLP service url callback
+ * 'dnssdStop()' - Stop all DNS-SD registrations.
  */
 
-static SLPBoolean                      /* O - TRUE = OK, FALSE = error */
-slp_url_callback(
-    SLPHandle      hslp,               /* I - SLP handle */
-    const char     *srvurl,            /* I - URL of service */
-    unsigned short lifetime,           /* I - Life of service */
-    SLPError       errcode,            /* I - Existing error code */
-    void           *cookie)            /* I - Pointer to service list */
+static void
+dnssdStop(void)
 {
-  slpsrvurl_t  *s,                     /* New service entry */
-               **head;                 /* Pointer to head of entry */
+  cupsd_printer_t      *p;             /* Current printer */
 
 
  /*
-  * Let the compiler know we won't be using these vars...
+  * De-register the individual printers
   */
 
-  (void)hslp;
-  (void)lifetime;
+  for (p = (cupsd_printer_t *)cupsArrayFirst(Printers);
+       p;
+       p = (cupsd_printer_t *)cupsArrayNext(Printers))
+    dnssdDeregisterPrinter(p);
 
  /*
-  * Bail if there was an error
+  * Shutdown the rest of the service refs...
   */
 
-  if (errcode != SLP_OK)
-    return (SLP_TRUE);
-
- /*
-  * Grab the head of the list...
-  */
+  if (WebIFRef)
+  {
+    DNSServiceRefDeallocate(WebIFRef);
+    WebIFRef = NULL;
+  }
 
-  head = (slpsrvurl_t**)cookie;
+  cupsdRemoveSelect(DNSServiceRefSockFD(DNSSDRef));
 
- /*
-  * Allocate a *temporary* slpsrvurl_t to hold this entry.
-  */
+  DNSServiceRefDeallocate(DNSSDRef);
+  DNSSDRef = NULL;
 
-  if ((s = (slpsrvurl_t *)calloc(1, sizeof(slpsrvurl_t))) == NULL)
-    return (SLP_FALSE);
+  cupsArrayDelete(DNSSDPrinters);
+  DNSSDPrinters = NULL;
 
- /*
-  * Copy the SLP service URL...
-  */
+  DNSSDPort = 0;
+}
 
-  strlcpy(s->url, srvurl, sizeof(s->url));
 
- /*
-  * Link the SLP service URL into the head of the list
 */
+/*
+ * 'dnssdUpdate()' - Handle DNS-SD queries.
+ */
 
-  if (*head)
-    s->next = *head;
+static void
+dnssdUpdate(void)
+{
+  DNSServiceErrorType  sdErr;          /* Service discovery error */
 
-  *head = s;
 
-  return (SLP_TRUE);
+  if ((sdErr = DNSServiceProcessResult(DNSSDRef)) != kDNSServiceErr_NoError)
+  {
+    cupsdLogMessage(CUPSD_LOG_ERROR,
+                    "DNS Service Discovery registration error %d!",
+                   sdErr);
+    dnssdStop();
+  }
 }
-#endif /* HAVE_LIBSLP */
+#endif /* HAVE_DNSSD */
 
 
 /*
- * 'update_cups_browse()' - Update the browse lists using the CUPS protocol.
+ * 'get_auth_info_required()' - Get the auth-info-required value to advertise.
  */
 
-static void
-update_cups_browse(void)
+static char *                          /* O - String or NULL if none */
+get_auth_info_required(
+    cupsd_printer_t *p,                        /* I - Printer */
+    char            *buffer,           /* I - Value buffer */
+    size_t          bufsize)           /* I - Size of value buffer */
 {
-  int          i;                      /* Looping var */
-  int          auth;                   /* Authorization status */
-  int          len;                    /* Length of name string */
-  int          bytes;                  /* Number of bytes left */
-  char         packet[1541],           /* Broadcast packet */
-               *pptr;                  /* Pointer into packet */
-  socklen_t    srclen;                 /* Length of source address */
-  http_addr_t  srcaddr;                /* Source address */
-  char         srcname[1024];          /* Source hostname */
-  unsigned     address[4];             /* Source address */
-  unsigned     type;                   /* Printer type */
-  unsigned     state;                  /* Printer state */
-  char         uri[HTTP_MAX_URI],      /* Printer URI */
-               host[HTTP_MAX_URI],     /* Host portion of URI */
-               resource[HTTP_MAX_URI], /* Resource portion of URI */
-               info[IPP_MAX_NAME],     /* Information string */
-               location[IPP_MAX_NAME], /* Location string */
-               make_model[IPP_MAX_NAME];/* Make and model string */
-  int          num_attrs;              /* Number of attributes */
-  cups_option_t        *attrs;                 /* Attributes */
+  cupsd_location_t *auth;              /* Pointer to authentication element */
+  char         resource[1024];         /* Printer/class resource path */
 
 
  /*
-  * Read a packet from the browse socket...
+  * If auth-info-required is set for this printer, return that...
   */
 
-  srclen = sizeof(srcaddr);
-  if ((bytes = recvfrom(BrowseSocket, packet, sizeof(packet) - 1, 0,
-                        (struct sockaddr *)&srcaddr, &srclen)) < 0)
+  if (p->num_auth_info_required > 0 && strcmp(p->auth_info_required[0], "none"))
   {
-   /*
-    * "Connection refused" is returned under Linux if the destination port
-    * or address is unreachable from a previous sendto(); check for the
-    * error here and ignore it for now...
-    */
+    int                i;                      /* Looping var */
+    char       *bufptr;                /* Pointer into buffer */
 
-    if (errno != ECONNREFUSED && errno != EAGAIN)
+    for (i = 0, bufptr = buffer; i < p->num_auth_info_required; i ++)
     {
-      cupsdLogMessage(CUPSD_LOG_ERROR, "Browse recv failed - %s.",
-                      strerror(errno));
-      cupsdLogMessage(CUPSD_LOG_ERROR, "CUPS browsing turned off.");
-
-#ifdef WIN32
-      closesocket(BrowseSocket);
-#else
-      close(BrowseSocket);
-#endif /* WIN32 */
+      if (bufptr >= (buffer + bufsize - 2))
+       break;
 
-      cupsdRemoveSelect(BrowseSocket);
-      BrowseSocket = -1;
+      if (i)
+       *bufptr++ = ',';
 
-      BrowseLocalProtocols  &= ~BROWSE_CUPS;
-      BrowseRemoteProtocols &= ~BROWSE_CUPS;
+      strlcpy(bufptr, p->auth_info_required[i], bufsize - (bufptr - buffer));
+      bufptr += strlen(bufptr);
     }
 
-    return;
+    return (buffer);
   }
 
-  packet[bytes] = '\0';
-
- /*
-  * If we're about to sleep, ignore incoming browse packets.
-  */
-
-  if (Sleeping)
-    return;
-
  /*
-  * Figure out where it came from...
+  * Figure out the authentication data requirements to advertise...
   */
 
-#ifdef AF_INET6
-  if (srcaddr.addr.sa_family == AF_INET6)
-  {
-    address[0] = ntohl(srcaddr.ipv6.sin6_addr.s6_addr32[0]);
-    address[1] = ntohl(srcaddr.ipv6.sin6_addr.s6_addr32[1]);
-    address[2] = ntohl(srcaddr.ipv6.sin6_addr.s6_addr32[2]);
-    address[3] = ntohl(srcaddr.ipv6.sin6_addr.s6_addr32[3]);
-  }
-  else
-#endif /* AF_INET6 */
-  {
-    address[0] = 0;
-    address[1] = 0;
-    address[2] = 0;
-    address[3] = ntohl(srcaddr.ipv4.sin_addr.s_addr);
-  }
-
-  if (HostNameLookups)
-    httpAddrLookup(&srcaddr, srcname, sizeof(srcname));
+  if (p->type & CUPS_PRINTER_CLASS)
+    snprintf(resource, sizeof(resource), "/classes/%s", p->name);
   else
-    httpAddrString(&srcaddr, srcname, sizeof(srcname));
-
-  len = strlen(srcname);
+    snprintf(resource, sizeof(resource), "/printers/%s", p->name);
 
- /*
-  * Do ACL stuff...
-  */
+  if ((auth = cupsdFindBest(resource, HTTP_POST)) == NULL ||
+      auth->type == CUPSD_AUTH_NONE)
+    auth = cupsdFindPolicyOp(p->op_policy_ptr, IPP_PRINT_JOB);
 
-  if (BrowseACL)
+  if (auth)
   {
-    if (httpAddrLocalhost(&srcaddr) || !_cups_strcasecmp(srcname, "localhost"))
-    {
-     /*
-      * Access from localhost (127.0.0.1) is always allowed...
-      */
+    int        auth_type;                      /* Authentication type */
 
-      auth = CUPSD_AUTH_ALLOW;
-    }
-    else
-    {
-     /*
-      * Do authorization checks on the domain/address...
-      */
+    if ((auth_type = auth->type) == CUPSD_AUTH_DEFAULT)
+      auth_type = DefaultAuthType;
 
-      switch (BrowseACL->order_type)
-      {
-        default :
-           auth = CUPSD_AUTH_DENY;     /* anti-compiler-warning-code */
-           break;
+    switch (auth_type)
+    {
+      case CUPSD_AUTH_NONE :
+          return (NULL);
 
-       case CUPSD_AUTH_ALLOW : /* Order Deny,Allow */
-            auth = CUPSD_AUTH_ALLOW;
+      case CUPSD_AUTH_NEGOTIATE :
+         strlcpy(buffer, "negotiate", bufsize);
+         break;
 
-            if (cupsdCheckAuth(address, srcname, len, BrowseACL->deny))
-             auth = CUPSD_AUTH_DENY;
+      default :
+         strlcpy(buffer, "username,password", bufsize);
+         break;
+    }
 
-            if (cupsdCheckAuth(address, srcname, len, BrowseACL->allow))
-             auth = CUPSD_AUTH_ALLOW;
-           break;
+    return (buffer);
+  }
 
-       case CUPSD_AUTH_DENY : /* Order Allow,Deny */
-            auth = CUPSD_AUTH_DENY;
+  return ("none");
+}
 
-            if (cupsdCheckAuth(address, srcname, len, BrowseACL->allow))
-             auth = CUPSD_AUTH_ALLOW;
 
-            if (cupsdCheckAuth(address, srcname, len, BrowseACL->deny))
-             auth = CUPSD_AUTH_DENY;
-           break;
-      }
-    }
-  }
-  else
-    auth = CUPSD_AUTH_ALLOW;
+#ifdef __APPLE__
+/*
+ * 'get_hostconfig()' - Get an /etc/hostconfig service setting.
+ */
 
-  if (auth == CUPSD_AUTH_DENY)
-  {
-    cupsdLogMessage(CUPSD_LOG_DEBUG,
-                    "update_cups_browse: Refused %d bytes from %s", bytes,
-                    srcname);
-    return;
-  }
+static int                             /* O - 1 for YES or AUTOMATIC, 0 for NO */
+get_hostconfig(const char *name)       /* I - Name of service */
+{
+  cups_file_t  *fp;                    /* Hostconfig file */
+  char         line[1024],             /* Line from file */
+               *ptr;                   /* Pointer to value */
+  int          state = 1;              /* State of service */
 
-  cupsdLogMessage(CUPSD_LOG_DEBUG2,
-                  "update_cups_browse: (%d bytes from %s) %s", bytes,
-                 srcname, packet);
 
  /*
-  * Parse packet...
+  * Try opening the /etc/hostconfig file; if we can't open it, assume that
+  * the service is enabled/auto.
   */
 
-  if (sscanf(packet, "%x%x%1023s", &type, &state, uri) < 3)
-  {
-    cupsdLogMessage(CUPSD_LOG_WARN,
-                    "update_cups_browse: Garbled browse packet - %s", packet);
-    return;
-  }
-
-  strcpy(location, "Location Unknown");
-  strcpy(info, "No Information Available");
-  make_model[0] = '\0';
-  num_attrs     = 0;
-  attrs         = NULL;
-
-  if ((pptr = strchr(packet, '\"')) != NULL)
+  if ((fp = cupsFileOpen("/etc/hostconfig", "r")) != NULL)
   {
    /*
-    * Have extended information; can't use sscanf for it because not all
-    * sscanf's allow empty strings with %[^\"]...
+    * Read lines from the file until we find the service...
     */
 
-    for (i = 0, pptr ++;
-         i < (sizeof(location) - 1) && *pptr && *pptr != '\"';
-         i ++, pptr ++)
-      location[i] = *pptr;
-
-    if (i)
-      location[i] = '\0';
-
-    if (*pptr == '\"')
-      pptr ++;
-
-    while (*pptr && isspace(*pptr & 255))
-      pptr ++;
-
-    if (*pptr == '\"')
+    while (cupsFileGets(fp, line, sizeof(line)))
     {
-      for (i = 0, pptr ++;
-           i < (sizeof(info) - 1) && *pptr && *pptr != '\"';
-           i ++, pptr ++)
-       info[i] = *pptr;
-
-      info[i] = '\0';
-
-      if (*pptr == '\"')
-       pptr ++;
+      if (line[0] == '#' || (ptr = strchr(line, '=')) == NULL)
+        continue;
 
-      while (*pptr && isspace(*pptr & 255))
-       pptr ++;
+      *ptr++ = '\0';
 
-      if (*pptr == '\"')
+      if (!_cups_strcasecmp(line, name))
       {
-       for (i = 0, pptr ++;
-             i < (sizeof(make_model) - 1) && *pptr && *pptr != '\"';
-             i ++, pptr ++)
-         make_model[i] = *pptr;
-
-       if (*pptr == '\"')
-         pptr ++;
-
-       make_model[i] = '\0';
+       /*
+        * Found the service, see if it is set to "-NO-"...
+       */
 
-        if (*pptr)
-         num_attrs = cupsParseOptions(pptr, num_attrs, &attrs);
+       if (!_cups_strncasecmp(ptr, "-NO-", 4))
+         state = 0;
+        break;
       }
     }
-  }
-
-  DEBUG_puts(packet);
-  DEBUG_printf(("type=%x, state=%x, uri=\"%s\"\n"
-                "location=\"%s\", info=\"%s\", make_model=\"%s\"\n",
-               type, state, uri, location, info, make_model));
-
- /*
-  * Pull the URI apart to see if this is a local or remote printer...
-  */
 
-  if (is_local_queue(uri, host, sizeof(host), resource, sizeof(resource)))
-  {
-    cupsFreeOptions(num_attrs, attrs);
-    return;
+    cupsFileClose(fp);
   }
 
- /*
-  * Do relaying...
-  */
-
-  for (i = 0; i < NumRelays; i ++)
-    if (cupsdCheckAuth(address, srcname, len, Relays[i].from))
-      if (sendto(BrowseSocket, packet, bytes, 0,
-                 (struct sockaddr *)&(Relays[i].to),
-                httpAddrLength(&(Relays[i].to))) <= 0)
-      {
-       cupsdLogMessage(CUPSD_LOG_ERROR,
-                       "update_cups_browse: sendto failed for relay %d - %s.",
-                       i + 1, strerror(errno));
-       cupsFreeOptions(num_attrs, attrs);
-       return;
-      }
-
- /*
-  * Process the browse data...
-  */
-
-  process_browse_data(uri, host, resource, (cups_ptype_t)type,
-                      (ipp_pstate_t)state, location, info, make_model,
-                     num_attrs, attrs);
+  return (state);
 }
+#endif /* __APPLE__ */
 
 
 /*
@@ -5472,41 +1313,6 @@ update_lpd(int onoff)                    /* - 1 = turn on, 0 = turn off */
 }
 
 
-/*
- * 'update_polling()' - Read status messages from the poll daemons.
- */
-
-static void
-update_polling(void)
-{
-  char         *ptr,                   /* Pointer to end of line in buffer */
-               message[1024];          /* Pointer to message text */
-  int          loglevel;               /* Log level for message */
-
-
-  while ((ptr = cupsdStatBufUpdate(PollStatusBuffer, &loglevel,
-                                   message, sizeof(message))) != NULL)
-  {
-    if (loglevel == CUPSD_LOG_INFO)
-      cupsdLogMessage(CUPSD_LOG_INFO, "%s", message);
-
-    if (!strchr(PollStatusBuffer->buffer, '\n'))
-      break;
-  }
-
-  if (ptr == NULL && !PollStatusBuffer->bufused)
-  {
-   /*
-    * All polling processes have died; stop polling...
-    */
-
-    cupsdLogMessage(CUPSD_LOG_ERROR,
-                    "update_polling: all polling processes have exited!");
-    cupsdStopPolling();
-  }
-}
-
-
 /*
  * 'update_smb()' - Update the SMB configuration as needed.
  */
index 933a057ba5cc615006a27cf11f339ddd8ee6d882..0625fd1ca1e503b6e0f284f00678161c05874a5f 100644 (file)
  *   file is missing or damaged, see the license at "http://www.cups.org/".
  */
 
-/*
- * Include necessary headers...
- */
-
-#ifdef HAVE_LIBSLP
-#  include <slp.h>
-#endif /* HAVE_LIBSLP */
-
-#ifdef HAVE_LDAP
-#  ifdef __sun
-#    include <lber.h>
-#  endif /* __sun */
-#  include <ldap.h>
-#  ifdef HAVE_LDAP_SSL_H
-#    include <ldap_ssl.h>
-#  endif /* HAVE_LDAP_SSL_H */
-#endif /* HAVE_LDAP */
-
 /*
  * Browse protocols...
  */
 
-#define BROWSE_CUPS    1               /* CUPS */
-#define        BROWSE_SLP      2               /* SLPv2 */
-#define BROWSE_LDAP    4               /* LDAP */
-#define BROWSE_DNSSD   8               /* DNS Service Discovery (aka Bonjour) */
-#define BROWSE_SMB     16              /* SMB/Samba */
-#define BROWSE_LPD     32              /* LPD via xinetd or launchd */
-#define BROWSE_ALL     63              /* All protocols */
-
-
-/*
- * Browse address...
- */
-
-typedef struct
-{
-  char                 iface[32];      /* Destination interface */
-  http_addr_t          to;             /* Destination address */
-} cupsd_dirsvc_addr_t;
-
-
-/*
- * Relay structure...
- */
-
-typedef struct
-{
-  cups_array_t         *from;          /* Source address/name mask(s) */
-  http_addr_t          to;             /* Destination address */
-} cupsd_dirsvc_relay_t;
-
-
-/*
- * Polling structure...
- */
-
-typedef struct
-{
-  char                 hostname[64];   /* Hostname (actually, IP address) */
-  int                  port;           /* Port number */
-  int                  pid;            /* Current poll server PID */
-} cupsd_dirsvc_poll_t;
+#define BROWSE_DNSSD   1               /* DNS Service Discovery (aka Bonjour) */
+#define BROWSE_SMB     2               /* SMB/Samba */
+#define BROWSE_LPD     4               /* LPD via xinetd or launchd */
+#define BROWSE_ALL     7               /* All protocols */
 
 
 /*
@@ -87,50 +32,8 @@ VAR int                      Browsing        VALUE(TRUE),
                        BrowseWebIF     VALUE(FALSE),
                                        /* Whether the web interface is advertised */
                        BrowseLocalProtocols
-                                       VALUE(BROWSE_ALL),
+                                       VALUE(BROWSE_ALL);
                                        /* Protocols to support for local printers */
-                       BrowseRemoteProtocols
-                                       VALUE(BROWSE_ALL),
-                                       /* Protocols to support for remote printers */
-                       BrowseShortNames VALUE(TRUE),
-                                       /* Short names for remote printers? */
-                       BrowseSocket    VALUE(-1),
-                                       /* Socket for browsing */
-                       BrowsePort      VALUE(IPP_PORT),
-                                       /* Port number for broadcasts */
-                       BrowseInterval  VALUE(DEFAULT_INTERVAL),
-                                       /* Broadcast interval in seconds */
-                       BrowseTimeout   VALUE(DEFAULT_TIMEOUT),
-                                       /* Time out for printers in seconds */
-                       UseNetworkDefault VALUE(CUPS_DEFAULT_USE_NETWORK_DEFAULT),
-                                       /* Use the network default printer? */
-                       NumBrowsers     VALUE(0);
-                                       /* Number of broadcast addresses */
-VAR char               *BrowseLocalOptions
-                                       VALUE(NULL),
-                                       /* Options to add to local printer URIs */
-                       *BrowseRemoteOptions
-                                       VALUE(NULL);
-                                       /* Options to add to remote printer URIs */
-VAR cupsd_dirsvc_addr_t        *Browsers       VALUE(NULL);
-                                       /* Broadcast addresses */
-VAR cupsd_location_t   *BrowseACL      VALUE(NULL);
-                                       /* Browser access control list */
-VAR cupsd_printer_t    *BrowseNext     VALUE(NULL);
-                                       /* Next class/printer to broadcast */
-VAR int                        NumRelays       VALUE(0);
-                                       /* Number of broadcast relays */
-VAR cupsd_dirsvc_relay_t *Relays       VALUE(NULL);
-                                       /* Broadcast relays */
-VAR int                        NumPolled       VALUE(0);
-                                       /* Number of polled servers */
-VAR cupsd_dirsvc_poll_t        *Polled         VALUE(NULL);
-                                       /* Polled servers */
-VAR int                        PollPipe        VALUE(0);
-                                       /* Status pipe for pollers */
-VAR cupsd_statbuf_t    *PollStatusBuffer VALUE(NULL);
-                                       /* Status buffer for pollers */
-
 #ifdef HAVE_DNSSD
 VAR char               *DNSSDComputerName VALUE(NULL),
                                        /* Computer/server name */
@@ -146,39 +49,10 @@ VAR cups_array_t   *DNSSDPrinters  VALUE(NULL);
                                        /* Printers we have registered */
 VAR DNSServiceRef      DNSSDRef        VALUE(NULL),
                                        /* Master DNS-SD service reference */
-                       WebIFRef        VALUE(NULL),
+                       WebIFRef        VALUE(NULL);
                                        /* Service reference for the web interface */
-                       RemoteRef       VALUE(NULL);
-                                       /* Remote printer browse reference */
 #endif /* HAVE_DNSSD */
 
-#ifdef HAVE_LIBSLP
-VAR SLPHandle          BrowseSLPHandle VALUE(NULL);
-                                       /* SLP API handle */
-VAR time_t             BrowseSLPRefresh VALUE(0);
-                                       /* Next SLP refresh time */
-#endif /* HAVE_LIBSLP */
-
-#ifdef HAVE_LDAP
-VAR LDAP               *BrowseLDAPHandle VALUE(NULL);
-                                       /* Handle to LDAP server */
-VAR time_t             BrowseLDAPRefresh VALUE(0);
-                                       /* Next LDAP refresh time */
-VAR char               *BrowseLDAPBindDN VALUE(NULL),
-                                       /* LDAP login DN */
-                       *BrowseLDAPDN   VALUE(NULL),
-                                       /* LDAP search DN */
-                       *BrowseLDAPPassword VALUE(NULL),
-                                       /* LDAP login password */
-                       *BrowseLDAPServer VALUE(NULL);
-                                       /* LDAP server to use */
-VAR int                        BrowseLDAPUpdate VALUE(TRUE);
-                                       /* enables LDAP updates */
-#  ifdef HAVE_LDAP_SSL
-VAR char               *BrowseLDAPCACertFile VALUE(NULL);
-                                       /* LDAP CA CERT file to use */
-#  endif /* HAVE_LDAP_SSL */
-#endif /* HAVE_LDAP */
 VAR char               *LPDConfigFile  VALUE(NULL),
                                        /* LPD configuration file */
                        *SMBConfigFile  VALUE(NULL);
@@ -190,22 +64,12 @@ VAR char           *LPDConfigFile  VALUE(NULL),
  */
 
 extern void    cupsdDeregisterPrinter(cupsd_printer_t *p, int removeit);
-extern void    cupsdLoadRemoteCache(void);
 extern void    cupsdRegisterPrinter(cupsd_printer_t *p);
-extern void    cupsdRestartPolling(void);
-extern void    cupsdSaveRemoteCache(void);
-extern void    cupsdSendBrowseList(void);
 extern void    cupsdStartBrowsing(void);
-extern void    cupsdStartPolling(void);
 extern void    cupsdStopBrowsing(void);
-extern void    cupsdStopPolling(void);
 #ifdef HAVE_DNSSD
 extern void    cupsdUpdateDNSSDName(void);
 #endif /* HAVE_DNSSD */
-#ifdef HAVE_LDAP
-extern void    cupsdUpdateLDAPBrowse(void);
-#endif /* HAVE_LDAP */
-extern void    cupsdUpdateSLPBrowse(void);
 
 
 /*
index 67ece2b5a0836f60d9974cfd44a29cdf595daae5..63e7e70627a7a1e861304dfd8ef021dbe2102c68 100644 (file)
@@ -45,7 +45,6 @@
  *                                 feed URI.
  *   check_quotas()              - Check quotas for a printer and user.
  *   close_job()                 - Close a multi-file job.
- *   copy_attribute()            - Copy a single attribute.
  *   copy_attrs()                - Copy attributes from one request to another.
  *   copy_banner()               - Copy a banner file to the requests directory
  *                                 for the specified job.
@@ -169,8 +168,6 @@ static void cancel_job(cupsd_client_t *con, ipp_attribute_t *uri);
 static void    cancel_subscription(cupsd_client_t *con, int id);
 static int     check_rss_recipient(const char *recipient);
 static int     check_quotas(cupsd_client_t *con, cupsd_printer_t *p);
-static ipp_attribute_t *copy_attribute(ipp_t *to, ipp_attribute_t *attr,
-                                       int quickcopy);
 static void    close_job(cupsd_client_t *con, ipp_attribute_t *uri);
 static void    copy_attrs(ipp_t *to, ipp_t *from, cups_array_t *ra,
                           ipp_tag_t group, int quickcopy,
@@ -850,8 +847,7 @@ cupsdTimeoutJob(cupsd_job_t *job)   /* I - Job to timeout */
   printer = cupsdFindDest(job->dest);
   attr    = ippFindAttribute(job->attrs, "job-sheets", IPP_TAG_NAME);
 
-  if (printer &&
-      !(printer->type & (CUPS_PRINTER_REMOTE | CUPS_PRINTER_IMPLICIT)) &&
+  if (printer && !(printer->type & CUPS_PRINTER_REMOTE) &&
       attr && attr->num_values > 1)
   {
    /*
@@ -966,7 +962,6 @@ add_class(cupsd_client_t  *con,             /* I - Client connection */
   cups_ptype_t dtype;                  /* Destination type */
   ipp_attribute_t *attr;               /* Printer attribute */
   int          modify;                 /* Non-zero if we just modified */
-  char         newname[IPP_MAX_NAME];  /* New class name */
   int          need_restart_job;       /* Need to restart job? */
 
 
@@ -1020,8 +1015,7 @@ add_class(cupsd_client_t  *con,           /* I - Client connection */
     * Class doesn't exist; see if we have a printer of the same name...
     */
 
-    if ((pclass = cupsdFindPrinter(resource + 9)) != NULL &&
-        !(pclass->type & CUPS_PRINTER_DISCOVERED))
+    if ((pclass = cupsdFindPrinter(resource + 9)) != NULL)
     {
      /*
       * Yes, return an error...
@@ -1046,56 +1040,6 @@ add_class(cupsd_client_t  *con,          /* I - Client connection */
     pclass = cupsdAddClass(resource + 9);
     modify = 0;
   }
-  else if (pclass->type & CUPS_PRINTER_IMPLICIT)
-  {
-   /*
-    * Check the default policy, then rename the implicit class to "AnyClass"
-    * or remove it...
-    */
-
-    if ((status = cupsdCheckPolicy(DefaultPolicyPtr, con, NULL)) != HTTP_OK)
-    {
-      send_http_error(con, status, NULL);
-      return;
-    }
-
-    if (ImplicitAnyClasses)
-    {
-      snprintf(newname, sizeof(newname), "Any%s", resource + 9);
-      cupsdRenamePrinter(pclass, newname);
-    }
-    else
-      cupsdDeletePrinter(pclass, 1);
-
-   /*
-    * Add the class as a new local class...
-    */
-
-    pclass = cupsdAddClass(resource + 9);
-    modify = 0;
-  }
-  else if (pclass->type & CUPS_PRINTER_DISCOVERED)
-  {
-   /*
-    * Check the default policy, then rename the remote class to "Class"...
-    */
-
-    if ((status = cupsdCheckPolicy(DefaultPolicyPtr, con, NULL)) != HTTP_OK)
-    {
-      send_http_error(con, status, NULL);
-      return;
-    }
-
-    snprintf(newname, sizeof(newname), "%s@%s", resource + 9, pclass->hostname);
-    cupsdRenamePrinter(pclass, newname);
-
-   /*
-    * Add the class as a new local class...
-    */
-
-    pclass = cupsdAddClass(resource + 9);
-    modify = 0;
-  }
   else if ((status = cupsdCheckPolicy(pclass->op_policy_ptr, con,
                                       NULL)) != HTTP_OK)
   {
@@ -1627,8 +1571,7 @@ add_job(cupsd_client_t  *con,             /* I - Client connection */
     return (NULL);
   }
 
-  job->dtype   = printer->type & (CUPS_PRINTER_CLASS | CUPS_PRINTER_IMPLICIT |
-                                  CUPS_PRINTER_REMOTE);
+  job->dtype   = printer->type & (CUPS_PRINTER_CLASS | CUPS_PRINTER_REMOTE);
   job->attrs   = con->request;
   job->dirty   = 1;
   con->request = ippNewRequest(job->attrs->request.op.operation_id);
@@ -1717,10 +1660,10 @@ add_job(cupsd_client_t  *con,           /* I - Client connection */
            {
              _cupsStrFree(attr->values[i].string.text);
              attr->values[i].string.text = NULL;
-             if (attr->values[i].string.charset)
+             if (attr->values[i].string.language)
              {
-               _cupsStrFree(attr->values[i].string.charset);
-               attr->values[i].string.charset = NULL;
+               _cupsStrFree(attr->values[i].string.language);
+               attr->values[i].string.language = NULL;
              }
             }
 
@@ -1813,8 +1756,7 @@ add_job(cupsd_client_t  *con,             /* I - Client connection */
     job->state_value              = IPP_JOB_PENDING;
   }
 
-  if (!(printer->type & (CUPS_PRINTER_REMOTE | CUPS_PRINTER_IMPLICIT)) ||
-      Classification)
+  if (!(printer->type & CUPS_PRINTER_REMOTE) || Classification)
   {
    /*
     * Add job sheets options...
@@ -1947,7 +1889,7 @@ add_job(cupsd_client_t  *con,             /* I - Client connection */
     * See if we need to add the starting sheet...
     */
 
-    if (!(printer->type & (CUPS_PRINTER_REMOTE | CUPS_PRINTER_IMPLICIT)))
+    if (!(printer->type & CUPS_PRINTER_REMOTE))
     {
       cupsdLogJob(job, CUPSD_LOG_INFO, "Adding start banner page \"%s\".",
                  attr->values[0].string.text);
@@ -2022,7 +1964,7 @@ add_job_state_reasons(
     cupsd_job_t    *job)               /* I - Job info */
 {
   cupsd_printer_t      *dest;          /* Destination printer */
-
+  ipp_attribute_t      *attr;          /* job-hold attribute */
 
   cupsdLogMessage(CUPSD_LOG_DEBUG2, "add_job_state_reasons(%p[%d], %d)",
                   con, con->http.fd, job ? job->id : 0);
@@ -2041,10 +1983,11 @@ add_job_state_reasons(
         break;
 
     case IPP_JOB_HELD :
-        if (ippFindAttribute(job->attrs, "job-hold-until",
-                            IPP_TAG_KEYWORD) != NULL ||
-           ippFindAttribute(job->attrs, "job-hold-until",
-                            IPP_TAG_NAME) != NULL)
+        if ((attr = ippFindAttribute(job->attrs, "job-hold-until",
+                                    IPP_TAG_KEYWORD)) == NULL)
+         attr = ippFindAttribute(job->attrs, "job-hold-until", IPP_TAG_NAME);
+
+       if (!attr || strcmp(attr->values[0].string.text, "no-hold"))
           ippAddString(con->response, IPP_TAG_JOB, IPP_TAG_KEYWORD,
                       "job-state-reasons", NULL, "job-hold-until-specified");
         else
@@ -2298,7 +2241,7 @@ add_job_subscriptions(
       * Free and remove this attribute...
       */
 
-      _ippFreeAttr(attr);
+      ippDeleteAttribute(NULL, attr);
 
       if (prev)
         prev->next = next;
@@ -2359,7 +2302,6 @@ add_printer(cupsd_client_t  *con, /* I - Client connection */
   char         srcfile[1024],          /* Source Script/PPD file */
                dstfile[1024];          /* Destination Script/PPD file */
   int          modify;                 /* Non-zero if we are modifying */
-  char         newname[IPP_MAX_NAME];  /* New printer name */
   int          changed_driver,         /* Changed the PPD/interface script? */
                need_restart_job,       /* Need to restart job? */
                set_device_uri,         /* Did we set the device URI? */
@@ -2415,8 +2357,7 @@ add_printer(cupsd_client_t  *con, /* I - Client connection */
     * Printer doesn't exist; see if we have a class of the same name...
     */
 
-    if ((printer = cupsdFindClass(resource + 10)) != NULL &&
-        !(printer->type & CUPS_PRINTER_DISCOVERED))
+    if ((printer = cupsdFindClass(resource + 10)) != NULL)
     {
      /*
       * Yes, return an error...
@@ -2441,58 +2382,6 @@ add_printer(cupsd_client_t  *con,        /* I - Client connection */
     printer = cupsdAddPrinter(resource + 10);
     modify  = 0;
   }
-  else if (printer->type & CUPS_PRINTER_IMPLICIT)
-  {
-   /*
-    * Check the default policy, then rename the implicit printer to
-    * "AnyPrinter" or delete it...
-    */
-
-    if ((status = cupsdCheckPolicy(DefaultPolicyPtr, con, NULL)) != HTTP_OK)
-    {
-      send_http_error(con, status, NULL);
-      return;
-    }
-
-    if (ImplicitAnyClasses)
-    {
-      snprintf(newname, sizeof(newname), "Any%s", resource + 10);
-      cupsdRenamePrinter(printer, newname);
-    }
-    else
-      cupsdDeletePrinter(printer, 1);
-
-   /*
-    * Add the printer as a new local printer...
-    */
-
-    printer = cupsdAddPrinter(resource + 10);
-    modify  = 0;
-  }
-  else if (printer->type & CUPS_PRINTER_DISCOVERED)
-  {
-   /*
-    * Check the default policy, then rename the remote printer to
-    * "Printer@server"...
-    */
-
-    if ((status = cupsdCheckPolicy(DefaultPolicyPtr, con, NULL)) != HTTP_OK)
-    {
-      send_http_error(con, status, NULL);
-      return;
-    }
-
-    snprintf(newname, sizeof(newname), "%s@%s", resource + 10,
-             printer->hostname);
-    cupsdRenamePrinter(printer, newname);
-
-   /*
-    * Add the printer as a new local printer...
-    */
-
-    printer = cupsdAddPrinter(resource + 10);
-    modify  = 0;
-  }
   else if ((status = cupsdCheckPolicy(printer->op_policy_ptr, con,
                                       NULL)) != HTTP_OK)
   {
@@ -4731,6 +4620,9 @@ check_quotas(cupsd_client_t  *con,        /* I - Client connection */
 
   strlcpy(username, get_username(con), sizeof(username));
 
+  if ((name = strchr(username, '@')) != NULL)
+    *name = '\0';                      /* Strip @REALM */
+
  /*
   * Check global active job limits for printers and users...
   */
@@ -5048,192 +4940,6 @@ close_job(cupsd_client_t  *con,         /* I - Client connection */
 }
 
 
-/*
- * 'copy_attribute()' - Copy a single attribute.
- */
-
-static ipp_attribute_t *               /* O - New attribute */
-copy_attribute(
-    ipp_t           *to,               /* O - Destination request/response */
-    ipp_attribute_t *attr,             /* I - Attribute to copy */
-    int             quickcopy)         /* I - Do a quick copy? */
-{
-  int                  i;              /* Looping var */
-  ipp_attribute_t      *toattr;        /* Destination attribute */
-
-
-  cupsdLogMessage(CUPSD_LOG_DEBUG2,
-                  "copy_attribute(%p, %p[%s,%x,%x])", to, attr,
-                 attr->name ? attr->name : "(null)", attr->group_tag,
-                 attr->value_tag);
-
-  switch (attr->value_tag & ~IPP_TAG_COPY)
-  {
-    case IPP_TAG_ZERO :
-        toattr = ippAddSeparator(to);
-       break;
-
-    case IPP_TAG_INTEGER :
-    case IPP_TAG_ENUM :
-        toattr = ippAddIntegers(to, attr->group_tag, attr->value_tag,
-                               attr->name, attr->num_values, NULL);
-
-        for (i = 0; i < attr->num_values; i ++)
-         toattr->values[i].integer = attr->values[i].integer;
-        break;
-
-    case IPP_TAG_BOOLEAN :
-        toattr = ippAddBooleans(to, attr->group_tag, attr->name,
-                               attr->num_values, NULL);
-
-        for (i = 0; i < attr->num_values; i ++)
-         toattr->values[i].boolean = attr->values[i].boolean;
-        break;
-
-    case IPP_TAG_STRING :
-    case IPP_TAG_TEXT :
-    case IPP_TAG_NAME :
-    case IPP_TAG_KEYWORD :
-    case IPP_TAG_URI :
-    case IPP_TAG_URISCHEME :
-    case IPP_TAG_CHARSET :
-    case IPP_TAG_LANGUAGE :
-    case IPP_TAG_MIMETYPE :
-        toattr = ippAddStrings(to, attr->group_tag,
-                              (ipp_tag_t)(attr->value_tag | quickcopy),
-                              attr->name, attr->num_values, NULL, NULL);
-
-        if (quickcopy)
-       {
-          for (i = 0; i < attr->num_values; i ++)
-           toattr->values[i].string.text = attr->values[i].string.text;
-        }
-       else if (attr->value_tag & IPP_TAG_COPY)
-       {
-          for (i = 0; i < attr->num_values; i ++)
-           toattr->values[i].string.text =
-               _cupsStrAlloc(attr->values[i].string.text);
-       }
-       else
-       {
-          for (i = 0; i < attr->num_values; i ++)
-           toattr->values[i].string.text =
-               _cupsStrRetain(attr->values[i].string.text);
-       }
-        break;
-
-    case IPP_TAG_DATE :
-        toattr = ippAddDate(to, attr->group_tag, attr->name,
-                           attr->values[0].date);
-        break;
-
-    case IPP_TAG_RESOLUTION :
-        toattr = ippAddResolutions(to, attr->group_tag, attr->name,
-                                  attr->num_values, IPP_RES_PER_INCH,
-                                  NULL, NULL);
-
-        for (i = 0; i < attr->num_values; i ++)
-       {
-         toattr->values[i].resolution.xres  = attr->values[i].resolution.xres;
-         toattr->values[i].resolution.yres  = attr->values[i].resolution.yres;
-         toattr->values[i].resolution.units = attr->values[i].resolution.units;
-       }
-        break;
-
-    case IPP_TAG_RANGE :
-        toattr = ippAddRanges(to, attr->group_tag, attr->name,
-                             attr->num_values, NULL, NULL);
-
-        for (i = 0; i < attr->num_values; i ++)
-       {
-         toattr->values[i].range.lower = attr->values[i].range.lower;
-         toattr->values[i].range.upper = attr->values[i].range.upper;
-       }
-        break;
-
-    case IPP_TAG_TEXTLANG :
-    case IPP_TAG_NAMELANG :
-        toattr = ippAddStrings(to, attr->group_tag,
-                              (ipp_tag_t)(attr->value_tag | quickcopy),
-                              attr->name, attr->num_values, NULL, NULL);
-
-        if (quickcopy)
-       {
-          for (i = 0; i < attr->num_values; i ++)
-         {
-            toattr->values[i].string.charset = attr->values[i].string.charset;
-           toattr->values[i].string.text    = attr->values[i].string.text;
-          }
-        }
-       else if (attr->value_tag & IPP_TAG_COPY)
-       {
-          for (i = 0; i < attr->num_values; i ++)
-         {
-           if (!i)
-              toattr->values[i].string.charset =
-                 _cupsStrAlloc(attr->values[i].string.charset);
-           else
-              toattr->values[i].string.charset =
-                 toattr->values[0].string.charset;
-
-           toattr->values[i].string.text =
-               _cupsStrAlloc(attr->values[i].string.text);
-          }
-        }
-       else
-       {
-          for (i = 0; i < attr->num_values; i ++)
-         {
-           if (!i)
-              toattr->values[i].string.charset =
-                 _cupsStrRetain(attr->values[i].string.charset);
-           else
-              toattr->values[i].string.charset =
-                 toattr->values[0].string.charset;
-
-           toattr->values[i].string.text =
-               _cupsStrRetain(attr->values[i].string.text);
-          }
-        }
-        break;
-
-    case IPP_TAG_BEGIN_COLLECTION :
-        toattr = ippAddCollections(to, attr->group_tag, attr->name,
-                                  attr->num_values, NULL);
-
-        for (i = 0; i < attr->num_values; i ++)
-       {
-         toattr->values[i].collection = attr->values[i].collection;
-         attr->values[i].collection->use ++;
-       }
-        break;
-
-    default :
-        toattr = ippAddIntegers(to, attr->group_tag, attr->value_tag,
-                               attr->name, attr->num_values, NULL);
-
-        for (i = 0; i < attr->num_values; i ++)
-       {
-         toattr->values[i].unknown.length = attr->values[i].unknown.length;
-
-         if (toattr->values[i].unknown.length > 0)
-         {
-           if ((toattr->values[i].unknown.data =
-                    malloc(toattr->values[i].unknown.length)) == NULL)
-             toattr->values[i].unknown.length = 0;
-           else
-             memcpy(toattr->values[i].unknown.data,
-                    attr->values[i].unknown.data,
-                    toattr->values[i].unknown.length);
-         }
-       }
-        break; /* anti-compiler-warning-code */
-  }
-
-  return (toattr);
-}
-
-
 /*
  * 'copy_attrs()' - Copy attributes from one request to another.
  */
@@ -5301,7 +5007,7 @@ copy_attrs(ipp_t        *to,              /* I - Destination request */
           !strcmp(fromattr->name, "media-col-database")))
        continue;
 
-      copy_attribute(to, fromattr, quickcopy);
+      ippCopyAttribute(to, fromattr, quickcopy);
     }
   }
 }
@@ -5983,8 +5689,8 @@ copy_job_attrs(cupsd_client_t *con,       /* I - Client connection */
   {
     httpAssembleURIf(HTTP_URI_CODING_ALL, job_uri, sizeof(job_uri), "ipp", NULL,
                     con->servername, con->serverport,
-                    job->dtype & (CUPS_PRINTER_IMPLICIT | CUPS_PRINTER_CLASS) ?
-                        "/classes/%s" : "/printers/%s",
+                    (job->dtype & CUPS_PRINTER_CLASS) ? "/classes/%s" :
+                                                        "/printers/%s",
                     job->dest);
     ippAddString(con->response, IPP_TAG_JOB, IPP_TAG_URI,
                 "job-printer-uri", NULL, job_uri);
@@ -6109,7 +5815,7 @@ copy_printer_attrs(
                    "stop-printer"
                  };
 
-    if (printer->type & (CUPS_PRINTER_IMPLICIT | CUPS_PRINTER_CLASS))
+    if (printer->type & CUPS_PRINTER_CLASS)
       ippAddString(con->response, IPP_TAG_PRINTER, IPP_TAG_NAME | IPP_TAG_COPY,
                    "printer-error-policy-supported", NULL, "retry-current-job");
     else
@@ -6136,8 +5842,7 @@ copy_printer_attrs(
     ippAddBoolean(con->response, IPP_TAG_PRINTER, "printer-is-shared",
                   printer->shared);
 
-  if ((!ra || cupsArrayFind(ra, "printer-more-info")) &&
-      !(printer->type & CUPS_PRINTER_DISCOVERED))
+  if (!ra || cupsArrayFind(ra, "printer-more-info"))
   {
     httpAssembleURIf(HTTP_URI_CODING_ALL, printer_uri, sizeof(printer_uri),
                      "http", NULL, con->servername, con->serverport,
@@ -6193,8 +5898,7 @@ copy_printer_attrs(
     ippAddInteger(con->response, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
                   "printer-up-time", curtime);
 
-  if ((!ra || cupsArrayFind(ra, "printer-uri-supported")) &&
-      !(printer->type & CUPS_PRINTER_DISCOVERED))
+  if (!ra || cupsArrayFind(ra, "printer-uri-supported"))
   {
     httpAssembleURIf(HTTP_URI_CODING_ALL, printer_uri, sizeof(printer_uri),
                      "ipp", NULL, con->servername, con->serverport,
@@ -8056,11 +7760,10 @@ get_ppd(cupsd_client_t  *con,           /* I - Client connection */
                    "printer-uri", NULL, dest->uri);
       return;
     }
-    else if (dtype & (CUPS_PRINTER_CLASS | CUPS_PRINTER_IMPLICIT))
+    else if (dtype & CUPS_PRINTER_CLASS)
     {
       for (i = 0; i < dest->num_printers; i ++)
-        if (!(dest->printers[i]->type &
-             (CUPS_PRINTER_CLASS | CUPS_PRINTER_IMPLICIT)))
+        if (!(dest->printers[i]->type & CUPS_PRINTER_CLASS))
        {
          snprintf(filename, sizeof(filename), "%s/ppd/%s.ppd", ServerRoot,
                   dest->printers[i]->name);
@@ -8507,15 +8210,6 @@ get_printers(cupsd_client_t *con,        /* I - Client connection */
        (!location ||
         (printer->location && !_cups_strcasecmp(printer->location, location))))
     {
-     /*
-      * If HideImplicitMembers is enabled, see if this printer or class
-      * is a member of an implicit class...
-      */
-
-      if (ImplicitClasses && HideImplicitMembers &&
-          printer->in_implicit_class)
-        continue;
-
      /*
       * If a username is specified, see if it is allowed or denied
       * access...
@@ -9741,14 +9435,14 @@ read_job_ticket(cupsd_client_t *con)    /* I - Client connection */
       if (con->request->last == attr2)
         con->request->last = prev2;
 
-      _ippFreeAttr(attr2);
+      ippDeleteAttribute(NULL, attr2);
     }
 
    /*
     * Add new option by copying it...
     */
 
-    copy_attribute(con->request, attr, 0);
+    ippCopyAttribute(con->request, attr, 0);
   }
 
  /*
@@ -11027,7 +10721,7 @@ set_default(cupsd_client_t  *con,       /* I - Client connection */
                "%s is now the default printer.", printer->name);
 
   cupsdMarkDirty(CUPSD_DIRTY_PRINTERS | CUPSD_DIRTY_CLASSES |
-                 CUPSD_DIRTY_REMOTE | CUPSD_DIRTY_PRINTCAP);
+                 CUPSD_DIRTY_PRINTCAP);
 
   cupsdLogMessage(CUPSD_LOG_INFO,
                   "Default destination set to \"%s\" by \"%s\".",
@@ -11205,9 +10899,8 @@ set_job_attrs(cupsd_client_t  *con,     /* I - Client connection */
       send_ipp_status(con, IPP_ATTRIBUTES_NOT_SETTABLE,
                       _("%s cannot be changed."), attr->name);
 
-      if ((attr2 = copy_attribute(con->response, attr, 0)) != NULL)
-        attr2->group_tag = IPP_TAG_UNSUPPORTED_GROUP;
-
+      attr2 = ippCopyAttribute(con->response, attr, 0);
+      ippSetGroupTag(con->response, &attr2, IPP_TAG_UNSUPPORTED_GROUP);
       continue;
     }
 
@@ -11221,8 +10914,8 @@ set_job_attrs(cupsd_client_t  *con,     /* I - Client connection */
       {
        send_ipp_status(con, IPP_REQUEST_VALUE, _("Bad job-priority value."));
 
-       if ((attr2 = copy_attribute(con->response, attr, 0)) != NULL)
-          attr2->group_tag = IPP_TAG_UNSUPPORTED_GROUP;
+       attr2 = ippCopyAttribute(con->response, attr, 0);
+       ippSetGroupTag(con->response, &attr2, IPP_TAG_UNSUPPORTED_GROUP);
       }
       else if (job->state_value >= IPP_JOB_PROCESSING)
       {
@@ -11251,8 +10944,8 @@ set_job_attrs(cupsd_client_t  *con,     /* I - Client connection */
       {
        send_ipp_status(con, IPP_REQUEST_VALUE, _("Bad job-state value."));
 
-       if ((attr2 = copy_attribute(con->response, attr, 0)) != NULL)
-          attr2->group_tag = IPP_TAG_UNSUPPORTED_GROUP;
+       attr2 = ippCopyAttribute(con->response, attr, 0);
+       ippSetGroupTag(con->response, &attr2, IPP_TAG_UNSUPPORTED_GROUP);
       }
       else
       {
@@ -11326,13 +11019,13 @@ set_job_attrs(cupsd_client_t  *con,   /* I - Client connection */
       if (job->attrs->last == attr2)
         job->attrs->last = job->attrs->prev;
 
-      _ippFreeAttr(attr2);
+      ippDeleteAttribute(NULL, attr2);
 
      /*
       * Then copy the attribute...
       */
 
-      copy_attribute(job->attrs, attr, 0);
+      ippCopyAttribute(job->attrs, attr, 0);
 
      /*
       * See if the job-name or job-hold-until is being changed.
@@ -11373,7 +11066,7 @@ set_job_attrs(cupsd_client_t  *con,     /* I - Client connection */
         if (attr2 == job->attrs->last)
          job->attrs->last = job->attrs->prev;
 
-        _ippFreeAttr(attr2);
+        ippDeleteAttribute(NULL, attr2);
 
         event |= CUPSD_EVENT_JOB_CONFIG_CHANGED;
       }
@@ -11384,7 +11077,7 @@ set_job_attrs(cupsd_client_t  *con,     /* I - Client connection */
       * Add new option by copying it...
       */
 
-      copy_attribute(job->attrs, attr, 0);
+      ippCopyAttribute(job->attrs, attr, 0);
 
       event |= CUPSD_EVENT_JOB_CONFIG_CHANGED;
     }
@@ -11649,7 +11342,7 @@ set_printer_defaults(
         continue;
 
       if (strcmp(attr->values[0].string.text, "retry-current-job") &&
-          ((printer->type & (CUPS_PRINTER_IMPLICIT | CUPS_PRINTER_CLASS)) ||
+          ((printer->type & CUPS_PRINTER_CLASS) ||
           (strcmp(attr->values[0].string.text, "abort-job") &&
            strcmp(attr->values[0].string.text, "retry-job") &&
            strcmp(attr->values[0].string.text, "stop-printer"))))
index 59e06dd55843bcf5feefcde1df6c37385fa9576d..b63eb36bd815318676328851ad4b2aec3bba100f 100644 (file)
@@ -362,8 +362,7 @@ cupsdCheckJobs(void)
       printer = cupsdFindDest(job->dest);
       pclass  = NULL;
 
-      while (printer &&
-             (printer->type & (CUPS_PRINTER_IMPLICIT | CUPS_PRINTER_CLASS)))
+      while (printer && (printer->type & CUPS_PRINTER_CLASS))
       {
        /*
         * If the class is remote, just pass it to the remote server...
@@ -415,10 +414,7 @@ cupsdCheckJobs(void)
           cupsdMarkDirty(CUPSD_DIRTY_JOBS);
        }
 
-        if ((!(printer->type & CUPS_PRINTER_DISCOVERED) && /* Printer is local */
-            printer->state == IPP_PRINTER_IDLE) ||     /* and idle, OR */
-           ((printer->type & CUPS_PRINTER_DISCOVERED) && /* Printer is remote */
-            !printer->job))                            /* and not printing */
+        if (printer->state == IPP_PRINTER_IDLE)
         {
         /*
          * Start the job...
@@ -748,7 +744,7 @@ cupsdContinueJob(cupsd_job_t *job)  /* I - Job */
                 job->job_sheets->values[0].string.text,
                 job->job_sheets->values[1].string.text);
 
-  if (job->printer->type & (CUPS_PRINTER_REMOTE | CUPS_PRINTER_IMPLICIT))
+  if (job->printer->type & CUPS_PRINTER_REMOTE)
     banner_page = 0;
   else if (job->job_sheets == NULL)
     banner_page = 0;
@@ -1006,7 +1002,7 @@ cupsdContinueJob(cupsd_job_t *job)        /* I - Job */
     envp[envc ++] = classification;
   }
 
-  if (job->dtype & (CUPS_PRINTER_CLASS | CUPS_PRINTER_IMPLICIT))
+  if (job->dtype & CUPS_PRINTER_CLASS)
   {
     snprintf(class_name, sizeof(class_name), "CLASS=%s", job->dest);
     envp[envc ++] = class_name;
@@ -1925,8 +1921,7 @@ cupsdMoveJob(cupsd_job_t     *job,        /* I - Job */
                p->name);
 
   cupsdSetString(&job->dest, p->name);
-  job->dtype = p->type & (CUPS_PRINTER_CLASS | CUPS_PRINTER_REMOTE |
-                          CUPS_PRINTER_IMPLICIT);
+  job->dtype = p->type & (CUPS_PRINTER_CLASS | CUPS_PRINTER_REMOTE);
 
   if ((attr = ippFindAttribute(job->attrs, "job-printer-uri",
                                IPP_TAG_URI)) != NULL)
@@ -2945,7 +2940,7 @@ finalize_job(cupsd_job_t *job,            /* I - Job */
          * act...
          */
 
-          if (job->dtype & (CUPS_PRINTER_CLASS | CUPS_PRINTER_IMPLICIT))
+          if (job->dtype & CUPS_PRINTER_CLASS)
          {
           /*
            * Queued on a class - mark the job as pending and we'll retry on
@@ -4417,10 +4412,7 @@ update_job(cupsd_job_t *job)             /* I - Job to check */
         cupsdSetAuthInfoRequired(job->printer, attr, NULL);
        cupsdSetPrinterAttrs(job->printer);
 
-       if (job->printer->type & CUPS_PRINTER_DISCOVERED)
-         cupsdMarkDirty(CUPSD_DIRTY_REMOTE);
-       else
-         cupsdMarkDirty(CUPSD_DIRTY_PRINTERS);
+       cupsdMarkDirty(CUPSD_DIRTY_PRINTERS);
       }
 
       if ((attr = cupsGetOption("job-media-progress", num_attrs,
index 0f4a711eaaf9b4da1e4a51b1b4f0b3db277bc514..7b7277175c5af075170aa794615498339162541f 100644 (file)
@@ -766,11 +766,9 @@ main(int  argc,                            /* I - Number of command-line args */
     * inactivity...
     */
 
-    if (timeout == 86400 && Launchd && LaunchdTimeout && !NumPolled &&
+    if (timeout == 86400 && Launchd && LaunchdTimeout &&
         !cupsArrayCount(ActiveJobs) &&
-       (!Browsing ||
-        (!BrowseRemoteProtocols &&
-         (!BrowseLocalProtocols || !cupsArrayCount(Printers)))))
+       (!Browsing || !BrowseLocalProtocols || !cupsArrayCount(Printers)))
     {
       timeout          = LaunchdTimeout;
       launchd_idle_exit = 1;
@@ -812,8 +810,6 @@ main(int  argc,                             /* I - Number of command-line args */
           i ++, lis = (cupsd_listener_t *)cupsArrayNext(Listeners))
         cupsdLogMessage(CUPSD_LOG_EMERG, "Listeners[%d] = %d", i, lis->fd);
 
-      cupsdLogMessage(CUPSD_LOG_EMERG, "BrowseSocket = %d", BrowseSocket);
-
       cupsdLogMessage(CUPSD_LOG_EMERG, "CGIPipes[0] = %d", CGIPipes[0]);
 
 #ifdef __APPLE__
@@ -914,31 +910,6 @@ main(int  argc,                            /* I - Number of command-line args */
       expire_time = current_time;
     }
 
-   /*
-    * Update the browse list as needed...
-    */
-
-    if (Browsing)
-    {
-#ifdef HAVE_LIBSLP
-      if ((BrowseRemoteProtocols & BROWSE_SLP) &&
-          BrowseSLPRefresh <= current_time)
-        cupsdUpdateSLPBrowse();
-#endif /* HAVE_LIBSLP */
-
-#ifdef HAVE_LDAP
-      if ((BrowseRemoteProtocols & BROWSE_LDAP) &&
-          BrowseLDAPRefresh <= current_time)
-        cupsdUpdateLDAPBrowse();
-#endif /* HAVE_LDAP */
-    }
-
-    if (Browsing && current_time > browse_time)
-    {
-      cupsdSendBrowseList();
-      browse_time = current_time;
-    }
-
 #ifndef HAVE_AUTHORIZATION_H
    /*
     * Update the root certificate once every 5 minutes if we have client
@@ -1031,8 +1002,6 @@ main(int  argc,                           /* I - Number of command-line args */
                       cupsArrayCount(ActiveJobs));
       cupsdLogMessage(CUPSD_LOG_DEBUG, "Report: printers=%d",
                       cupsArrayCount(Printers));
-      cupsdLogMessage(CUPSD_LOG_DEBUG, "Report: printers-implicit=%d",
-                      cupsArrayCount(ImplicitPrinters));
 
       string_count = _cupsStrStatistics(&alloc_bytes, &total_bytes);
       cupsdLogMessage(CUPSD_LOG_DEBUG,
@@ -1512,10 +1481,8 @@ launchd_checkout(void)
   * shared printers to advertise...
   */
 
-  if (cupsArrayCount(ActiveJobs) || NumPolled ||
-      (Browsing &&
-       (BrowseRemoteProtocols ||
-        (BrowseLocalProtocols && cupsArrayCount(Printers)))))
+  if (cupsArrayCount(ActiveJobs) ||
+      (Browsing && BrowseLocalProtocols && cupsArrayCount(Printers)))
   {
     cupsdLogMessage(CUPSD_LOG_DEBUG,
                     "Creating launchd keepalive file \"" CUPS_KEEPALIVE
@@ -1773,7 +1740,6 @@ select_timeout(int fds)                   /* I - Number of descriptors returned */
   long                 timeout;        /* Timeout for select */
   time_t               now;            /* Current time */
   cupsd_client_t       *con;           /* Client information */
-  cupsd_printer_t      *p;             /* Printer information */
   cupsd_job_t          *job;           /* Job information */
   cupsd_subscription_t *sub;           /* Subscription information */
   const char           *why;           /* Debugging aid */
@@ -1847,54 +1813,6 @@ select_timeout(int fds)                  /* I - Number of descriptors returned */
       why     = "timeout a client connection";
     }
 
- /*
-  * Update the browse list as needed...
-  */
-
-  if (Browsing && BrowseLocalProtocols)
-  {
-#ifdef HAVE_LIBSLP
-    if ((BrowseLocalProtocols & BROWSE_SLP) && (BrowseSLPRefresh < timeout))
-    {
-      timeout = BrowseSLPRefresh;
-      why     = "update SLP browsing";
-    }
-#endif /* HAVE_LIBSLP */
-
-#ifdef HAVE_LDAP
-    if ((BrowseLocalProtocols & BROWSE_LDAP) && (BrowseLDAPRefresh < timeout))
-    {
-      timeout = BrowseLDAPRefresh;
-      why     = "update LDAP browsing";
-    }
-#endif /* HAVE_LDAP */
-
-    if ((BrowseLocalProtocols & BROWSE_CUPS) && NumBrowsers)
-    {
-      for (p = (cupsd_printer_t *)cupsArrayFirst(Printers);
-           p;
-          p = (cupsd_printer_t *)cupsArrayNext(Printers))
-      {
-       if (p->type & CUPS_PRINTER_REMOTE)
-       {
-         if ((p->browse_time + BrowseTimeout) < timeout)
-         {
-           timeout = p->browse_time + BrowseTimeout;
-           why     = "browse timeout a printer";
-         }
-       }
-       else if (p->shared && !(p->type & CUPS_PRINTER_IMPLICIT))
-       {
-         if (BrowseInterval && (p->browse_time + BrowseInterval) < timeout)
-         {
-           timeout = p->browse_time + BrowseInterval;
-           why     = "send browse update";
-         }
-       }
-      }
-    }
-  }
-
  /*
   * Write out changes to configuration and state files...
   */
index 6e9705893fbf2ec342108bb8addbc9bd35fabd89..fd6216ba4d7c1503feaf6ee027085fc1fb5b5199 100644 (file)
@@ -168,9 +168,6 @@ cupsdAddPrinter(const char *name)   /* I - Name of printer */
                   "cupsdAddPrinter: Adding %s to Printers", p->name);
   cupsArrayAdd(Printers, p);
 
-  if (!ImplicitPrinters)
-    ImplicitPrinters = cupsArrayNew(compare_printers, NULL);
-
  /*
   * Return the new printer...
   */
@@ -751,16 +748,6 @@ cupsdDeletePrinter(
                      update ? "Job stopped due to printer being deleted." :
                              "Job stopped.");
 
- /*
-  * If this printer is the next for browsing, point to the next one...
-  */
-
-  if (p == BrowseNext)
-  {
-    cupsArrayFind(Printers, p);
-    BrowseNext = (cupsd_printer_t *)cupsArrayNext(Printers);
-  }
-
  /*
   * Remove the printer from the list...
   */
@@ -769,14 +756,6 @@ cupsdDeletePrinter(
                   "cupsdDeletePrinter: Removing %s from Printers", p->name);
   cupsArrayRemove(Printers, p);
 
-  if (p->type & CUPS_PRINTER_IMPLICIT)
-  {
-    cupsdLogMessage(CUPSD_LOG_DEBUG2,
-                   "cupsdDeletePrinter: Removing %s from ImplicitPrinters",
-                   p->name);
-    cupsArrayRemove(ImplicitPrinters, p);
-  }
-
  /*
   * Remove the dummy interface/icon/option files under IRIX...
   */
@@ -807,43 +786,19 @@ cupsdDeletePrinter(
   */
 
   if (p == DefaultPrinter)
-  {
     DefaultPrinter = NULL;
 
-    if (UseNetworkDefault)
-    {
-     /*
-      * Find the first network default printer and use it...
-      */
-
-      cupsd_printer_t  *dp;            /* New default printer */
-
-
-      for (dp = (cupsd_printer_t *)cupsArrayFirst(Printers);
-          dp;
-          dp = (cupsd_printer_t *)cupsArrayNext(Printers))
-       if (dp != p && (dp->type & CUPS_PRINTER_DEFAULT))
-       {
-         DefaultPrinter = dp;
-         break;
-       }
-    }
-  }
-
  /*
   * Remove this printer from any classes...
   */
 
-  if (!(p->type & CUPS_PRINTER_IMPLICIT))
-  {
-    changed = cupsdDeletePrinterFromClasses(p);
+  changed = cupsdDeletePrinterFromClasses(p);
 
  /*
-    * Deregister from any browse protocols...
-    */
+ /*
+  * Deregister from any browse protocols...
+  */
 
-    cupsdDeregisterPrinter(p, 1);
-  }
+  cupsdDeregisterPrinter(p, 1);
 
  /*
   * Free all memory used by the printer...
@@ -889,9 +844,6 @@ cupsdDeletePrinter(
 
   cupsArrayDelete(p->filetypes);
 
-  if (p->browse_attrs)
-    free(p->browse_attrs);
-
   cupsFreeOptions(p->num_options, p->options);
 
   free(p);
@@ -1396,14 +1348,6 @@ cupsdRenamePrinter(
                   "cupsdRenamePrinter: Removing %s from Printers", p->name);
   cupsArrayRemove(Printers, p);
 
-  if (p->type & CUPS_PRINTER_IMPLICIT)
-  {
-    cupsdLogMessage(CUPSD_LOG_DEBUG2,
-                   "cupsdRenamePrinter: Removing %s from ImplicitPrinters",
-                   p->name);
-    cupsArrayRemove(ImplicitPrinters, p);
-  }
-
  /*
   * Rename the printer type...
   */
@@ -1436,14 +1380,6 @@ cupsdRenamePrinter(
   cupsdLogMessage(CUPSD_LOG_DEBUG2,
                   "cupsdRenamePrinter: Adding %s to Printers", p->name);
   cupsArrayAdd(Printers, p);
-
-  if (p->type & CUPS_PRINTER_IMPLICIT)
-  {
-    cupsdLogMessage(CUPSD_LOG_DEBUG2,
-                   "cupsdRenamePrinter: Adding %s to ImplicitPrinters",
-                   p->name);
-    cupsArrayAdd(ImplicitPrinters, p);
-  }
 }
 
 
@@ -1501,12 +1437,10 @@ cupsdSaveAllPrinters(void)
        printer = (cupsd_printer_t *)cupsArrayNext(Printers))
   {
    /*
-    * Skip remote destinations and printer classes...
+    * Skip printer classes...
     */
 
-    if ((printer->type & CUPS_PRINTER_DISCOVERED) ||
-        (printer->type & CUPS_PRINTER_CLASS) ||
-       (printer->type & CUPS_PRINTER_IMPLICIT))
+    if (printer->type & CUPS_PRINTER_CLASS)
       continue;
 
    /*
@@ -2106,8 +2040,7 @@ cupsdSetPrinterAttr(
 void
 cupsdSetPrinterAttrs(cupsd_printer_t *p)/* I - Printer to setup */
 {
-  int          i,                      /* Looping var */
-               length;                 /* Length of browse attributes */
+  int          i;                      /* Looping var */
   char         resource[HTTP_MAX_URI]; /* Resource portion of URI */
   int          num_air;                /* Number of auth-info-required values */
   const char   * const *air;           /* auth-info-required values */
@@ -2115,7 +2048,6 @@ cupsdSetPrinterAttrs(cupsd_printer_t *p)/* I - Printer to setup */
   const char   *auth_supported;        /* Authentication supported */
   ipp_t                *oldattrs;              /* Old printer attributes */
   ipp_attribute_t *attr;               /* Attribute data */
-  cups_option_t        *option;                /* Current printer option */
   char         *name,                  /* Current user/group name */
                *filter;                /* Current filter */
   static const char * const air_none[] =
@@ -2158,8 +2090,7 @@ cupsdSetPrinterAttrs(cupsd_printer_t *p)/* I - Printer to setup */
     num_air = p->num_auth_info_required;
     air     = p->auth_info_required;
   }
-  else if ((p->type & CUPS_PRINTER_AUTHENTICATED) &&
-           (p->type & CUPS_PRINTER_DISCOVERED))
+  else if (p->type & CUPS_PRINTER_AUTHENTICATED)
   {
     num_air = 2;
     air     = air_userpass;
@@ -2191,15 +2122,12 @@ cupsdSetPrinterAttrs(cupsd_printer_t *p)/* I - Printer to setup */
       auth_supported = "negotiate";
 #endif /* HAVE_GSSAPI */
 
-    if (!(p->type & CUPS_PRINTER_DISCOVERED))
-    {
-      if (auth_type != CUPSD_AUTH_NONE)
-       p->type |= CUPS_PRINTER_AUTHENTICATED;
-      else
-       p->type &= ~CUPS_PRINTER_AUTHENTICATED;
-    }
+    if (auth_type != CUPSD_AUTH_NONE)
+      p->type |= CUPS_PRINTER_AUTHENTICATED;
+    else
+      p->type &= ~CUPS_PRINTER_AUTHENTICATED;
   }
-  else if (!(p->type & CUPS_PRINTER_DISCOVERED))
+  else
     p->type &= ~CUPS_PRINTER_AUTHENTICATED;
 
  /*
@@ -2248,7 +2176,7 @@ cupsdSetPrinterAttrs(cupsd_printer_t *p)/* I - Printer to setup */
   ippAddStrings(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD,
                "auth-info-required", num_air, NULL, air);
 
-  if (cupsArrayCount(Banners) > 0 && !(p->type & CUPS_PRINTER_DISCOVERED))
+  if (cupsArrayCount(Banners) > 0)
   {
    /*
     * Setup the job-sheets-default attribute...
@@ -2269,164 +2197,117 @@ cupsdSetPrinterAttrs(cupsd_printer_t *p)/* I - Printer to setup */
   p->raw    = 0;
   p->remote = 0;
 
-  if (p->type & CUPS_PRINTER_DISCOVERED)
+ /*
+  * Assign additional attributes depending on whether this is a printer
+  * or class...
+  */
+
+  if (p->type & CUPS_PRINTER_CLASS)
   {
+    p->raw = 1;
+    p->type &= ~CUPS_PRINTER_OPTIONS;
+
    /*
-    * Tell the client this is a remote printer of some type...
+    * Add class-specific attributes...
     */
 
-    if (strchr(p->uri, '?'))
+    ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_TEXT,
+                "printer-make-and-model", NULL, "Local Printer Class");
+    ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_URI, "device-uri", NULL,
+                "file:///dev/null");
+
+    if (p->num_printers > 0)
     {
      /*
-      * Strip trailing "?options" from URI...
+      * Add a list of member names; URIs are added in copy_printer_attrs...
       */
 
-      char *ptr;                       /* Pointer into URI */
+      attr    = ippAddStrings(p->attrs, IPP_TAG_PRINTER, IPP_TAG_NAME,
+                             "member-names", p->num_printers, NULL, NULL);
+      p->type |= CUPS_PRINTER_OPTIONS;
 
-      strlcpy(resource, p->uri, sizeof(resource));
-      if ((ptr = strchr(resource, '?')) != NULL)
-        *ptr = '\0';
+      for (i = 0; i < p->num_printers; i ++)
+      {
+       if (attr != NULL)
+         attr->values[i].string.text = _cupsStrRetain(p->printers[i]->name);
 
-      ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_URI,
-                  "printer-uri-supported", NULL, resource);
+       p->type &= ~CUPS_PRINTER_OPTIONS | p->printers[i]->type;
+      }
     }
-    else
-      ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_URI,
-                  "printer-uri-supported", NULL, p->uri);
-
-    ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_URI, "printer-more-info",
-                NULL, p->uri);
-
-    if (p->make_model)
-      ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_TEXT,
-                   "printer-make-and-model", NULL, p->make_model);
-
-    ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_URI, "device-uri", NULL,
-                p->uri);
-
-    p->raw    = 1;
-    p->remote = 1;
   }
   else
   {
    /*
-    * Assign additional attributes depending on whether this is a printer
-    * or class...
+    * Add printer-specific attributes...
     */
 
-    if (p->type & (CUPS_PRINTER_CLASS | CUPS_PRINTER_IMPLICIT))
-    {
-      p->raw = 1;
-      p->type &= ~CUPS_PRINTER_OPTIONS;
-
-     /*
-      * Add class-specific attributes...
-      */
-
-      if ((p->type & CUPS_PRINTER_IMPLICIT) && p->num_printers > 0 &&
-          p->printers[0]->make_model)
-       ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_TEXT,
-                     "printer-make-and-model", NULL, p->printers[0]->make_model);
-      else
-       ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_TEXT,
-                     "printer-make-and-model", NULL, "Local Printer Class");
+    ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_URI, "device-uri", NULL,
+                p->sanitized_device_uri);
 
-      ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_URI, "device-uri", NULL,
-                  "file:///dev/null");
+   /*
+    * Assign additional attributes from the PPD file (if any)...
+    */
 
-      if (p->num_printers > 0)
-      {
-       /*
-       * Add a list of member names; URIs are added in copy_printer_attrs...
-       */
+    load_ppd(p);
 
-       attr    = ippAddStrings(p->attrs, IPP_TAG_PRINTER, IPP_TAG_NAME,
-                                "member-names", p->num_printers, NULL, NULL);
-        p->type |= CUPS_PRINTER_OPTIONS;
+   /*
+    * Add filters for printer...
+    */
 
-       for (i = 0; i < p->num_printers; i ++)
-       {
-          if (attr != NULL)
-            attr->values[i].string.text = _cupsStrRetain(p->printers[i]->name);
+    cupsdSetPrinterReasons(p, "-cups-missing-filter-warning,"
+                             "cups-insecure-filter-warning");
 
-         p->type &= ~CUPS_PRINTER_OPTIONS | p->printers[i]->type;
-        }
-      }
+    if (p->pc && p->pc->filters)
+    {
+      for (filter = (char *)cupsArrayFirst(p->pc->filters);
+          filter;
+          filter = (char *)cupsArrayNext(p->pc->filters))
+       add_printer_filter(p, p->filetype, filter);
     }
-    else
+    else if (!(p->type & CUPS_PRINTER_REMOTE))
     {
-     /*
-      * Add printer-specific attributes...
-      */
+      char     interface[1024];        /* Interface script */
 
-      ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_URI, "device-uri", NULL,
-                  p->sanitized_device_uri);
 
-     /*
-      * Assign additional attributes from the PPD file (if any)...
-      */
-
-      load_ppd(p);
-
-     /*
-      * Add filters for printer...
-      */
-
-      cupsdSetPrinterReasons(p, "-cups-missing-filter-warning,"
-                                "cups-insecure-filter-warning");
-
-      if (p->pc && p->pc->filters)
+      snprintf(interface, sizeof(interface), "%s/interfaces/%s", ServerRoot,
+              p->name);
+      if (!access(interface, X_OK))
       {
-       for (filter = (char *)cupsArrayFirst(p->pc->filters);
-            filter;
-            filter = (char *)cupsArrayNext(p->pc->filters))
-         add_printer_filter(p, p->filetype, filter);
+       /*
+       * Yes, we have a System V style interface script; use it!
+       */
+
+       snprintf(interface, sizeof(interface), "*/* 0 %s/interfaces/%s",
+                ServerRoot, p->name);
+       add_printer_filter(p, p->filetype, interface);
       }
-      else if (!(p->type & CUPS_PRINTER_REMOTE))
+      else
       {
-       char    interface[1024];        /* Interface script */
-
-
-       snprintf(interface, sizeof(interface), "%s/interfaces/%s", ServerRoot,
-                p->name);
-       if (!access(interface, X_OK))
-       {
-        /*
-         * Yes, we have a System V style interface script; use it!
-         */
-
-         snprintf(interface, sizeof(interface), "*/* 0 %s/interfaces/%s",
-                  ServerRoot, p->name);
-         add_printer_filter(p, p->filetype, interface);
-       }
-       else
-       {
-        /*
-         * Add a filter from application/vnd.cups-raw to printer/name to
-         * handle "raw" printing by users.
-         */
+       /*
+       * Add a filter from application/vnd.cups-raw to printer/name to
+       * handle "raw" printing by users.
+       */
 
-         add_printer_filter(p, p->filetype, "application/vnd.cups-raw 0 -");
+       add_printer_filter(p, p->filetype, "application/vnd.cups-raw 0 -");
 
-        /*
-         * Add a PostScript filter, since this is still possibly PS printer.
-         */
+       /*
+       * Add a PostScript filter, since this is still possibly PS printer.
+       */
 
-         add_printer_filter(p, p->filetype,
-                            "application/vnd.cups-postscript 0 -");
-       }
+       add_printer_filter(p, p->filetype,
+                          "application/vnd.cups-postscript 0 -");
       }
+    }
 
-      if (p->pc && p->pc->prefilters)
-      {
-        if (!p->prefiltertype)
-          p->prefiltertype = mimeAddType(MimeDatabase, "prefilter", p->name);
+    if (p->pc && p->pc->prefilters)
+    {
+      if (!p->prefiltertype)
+       p->prefiltertype = mimeAddType(MimeDatabase, "prefilter", p->name);
 
-        for (filter = (char *)cupsArrayFirst(p->pc->prefilters);
-            filter;
-            filter = (char *)cupsArrayNext(p->pc->prefilters))
-         add_printer_filter(p, p->prefiltertype, filter);
-      }
+      for (filter = (char *)cupsArrayFirst(p->pc->prefilters);
+          filter;
+          filter = (char *)cupsArrayNext(p->pc->prefilters))
+       add_printer_filter(p, p->prefiltertype, filter);
     }
   }
 
@@ -2526,98 +2407,8 @@ cupsdSetPrinterAttrs(cupsd_printer_t *p)/* I - Printer to setup */
   * Force sharing off for remote queues...
   */
 
-  if (p->type & (CUPS_PRINTER_REMOTE | CUPS_PRINTER_IMPLICIT))
+  if (p->type & CUPS_PRINTER_REMOTE)
     p->shared = 0;
-  else
-  {
-   /*
-    * Copy the printer options into a browse attributes string we can re-use.
-    */
-
-    const char *valptr;                /* Pointer into value */
-    char       *attrptr;               /* Pointer into attribute string */
-
-
-   /*
-    * Free the old browse attributes as needed...
-    */
-
-    if (p->browse_attrs)
-      free(p->browse_attrs);
-
-   /*
-    * Compute the length of all attributes + job-sheets, lease-duration,
-    * and BrowseLocalOptions.
-    */
-
-    for (length = 1, i = p->num_options, option = p->options;
-         i > 0;
-        i --, option ++)
-    {
-      length += strlen(option->name) + 2;
-
-      if (option->value)
-      {
-        for (valptr = option->value; *valptr; valptr ++)
-         if (strchr(" \"\'\\", *valptr))
-           length += 2;
-         else
-           length ++;
-      }
-    }
-
-    length += 13 + strlen(p->job_sheets[0]) + strlen(p->job_sheets[1]);
-    length += 32;
-    if (BrowseLocalOptions)
-      length += 12 + strlen(BrowseLocalOptions);
-
-   /*
-    * Allocate the new string...
-    */
-
-    if ((p->browse_attrs = calloc(1, length)) == NULL)
-      cupsdLogMessage(CUPSD_LOG_ERROR,
-                      "Unable to allocate %d bytes for browse data!",
-                     length);
-    else
-    {
-     /*
-      * Got the allocated string, now copy the options and attributes over...
-      */
-
-      sprintf(p->browse_attrs, "job-sheets=%s,%s lease-duration=%d",
-              p->job_sheets[0], p->job_sheets[1], BrowseTimeout);
-      attrptr = p->browse_attrs + strlen(p->browse_attrs);
-
-      if (BrowseLocalOptions)
-      {
-        sprintf(attrptr, " ipp-options=%s", BrowseLocalOptions);
-        attrptr += strlen(attrptr);
-      }
-
-      for (i = p->num_options, option = p->options;
-           i > 0;
-          i --, option ++)
-      {
-        *attrptr++ = ' ';
-       strcpy(attrptr, option->name);
-       attrptr += strlen(attrptr);
-
-       if (option->value)
-       {
-         *attrptr++ = '=';
-
-          for (valptr = option->value; *valptr; valptr ++)
-         {
-           if (strchr(" \"\'\\", *valptr))
-             *attrptr++ = '\\';
-
-           *attrptr++ = *valptr;
-         }
-       }
-      }
-    }
-  }
 
  /*
   * Populate the document-format-supported attribute...
@@ -2809,13 +2600,6 @@ cupsdSetPrinterState(
   };
 
 
- /*
-  * Can't set status of remote printers...
-  */
-
-  if (p->type & CUPS_PRINTER_DISCOVERED)
-    return;
-
  /*
   * Set the new state...
   */
@@ -2835,9 +2619,7 @@ cupsdSetPrinterState(
     * Let the browse code know this needs to be updated...
     */
 
-    BrowseNext     = p;
-    p->state_time  = time(NULL);
-    p->browse_time = 0;
+    p->state_time = time(NULL);
 
 #ifdef __sgi
     write_irix_state(p);
@@ -3035,22 +2817,6 @@ cupsdUpdatePrinters(void)
        p;
        p = (cupsd_printer_t *)cupsArrayNext(Printers))
   {
-   /*
-    * Remove remote printers if we are no longer browsing...
-    */
-
-    if (!Browsing &&
-        (p->type & (CUPS_PRINTER_IMPLICIT | CUPS_PRINTER_DISCOVERED)))
-    {
-      if (p->type & CUPS_PRINTER_IMPLICIT)
-        cupsArrayRemove(ImplicitPrinters, p);
-
-      cupsArraySave(Printers);
-      cupsdDeletePrinter(p, 0);
-      cupsArrayRestore(Printers);
-      continue;
-    }
-
    /*
     * Update the operation policy pointer...
     */
@@ -3059,11 +2825,10 @@ cupsdUpdatePrinters(void)
       p->op_policy_ptr = DefaultPolicyPtr;
 
    /*
-    * Update printer attributes as needed...
+    * Update printer attributes...
     */
 
-    if (!(p->type & CUPS_PRINTER_DISCOVERED))
-      cupsdSetPrinterAttrs(p);
+    cupsdSetPrinterAttrs(p);
   }
 }
 
@@ -3156,8 +2921,7 @@ cupsdValidateDest(
       *printer = p;
 
     if (dtype)
-      *dtype = p->type & (CUPS_PRINTER_CLASS | CUPS_PRINTER_IMPLICIT |
-                          CUPS_PRINTER_REMOTE | CUPS_PRINTER_DISCOVERED);
+      *dtype = p->type & (CUPS_PRINTER_CLASS | CUPS_PRINTER_REMOTE);
 
     return (p->name);
   }
@@ -3215,8 +2979,7 @@ cupsdValidateDest(
         *printer = p;
 
       if (dtype)
-       *dtype = p->type & (CUPS_PRINTER_CLASS | CUPS_PRINTER_IMPLICIT |
-                            CUPS_PRINTER_REMOTE | CUPS_PRINTER_DISCOVERED);
+       *dtype = p->type & (CUPS_PRINTER_CLASS | CUPS_PRINTER_REMOTE);
 
       return (p->name);
     }
@@ -3899,9 +3662,7 @@ delete_printer_filters(
 static void
 dirty_printer(cupsd_printer_t *p)      /* I - Printer */
 {
-  if (p->type & CUPS_PRINTER_DISCOVERED)
-    cupsdMarkDirty(CUPSD_DIRTY_REMOTE);
-  else if (p->type & CUPS_PRINTER_CLASS)
+  if (p->type & CUPS_PRINTER_CLASS)
     cupsdMarkDirty(CUPSD_DIRTY_CLASSES);
   else
     cupsdMarkDirty(CUPSD_DIRTY_PRINTERS);
@@ -3941,7 +3702,7 @@ load_ppd(cupsd_printer_t *p)              /* I - Printer */
   _pwg_map_t   *pwgsource,             /* Current PWG source */
                *pwgtype;               /* Current PWG type */
   ipp_attribute_t *attr;               /* Attribute data */
-  ipp_value_t  *val;                   /* Attribute value */
+  _ipp_value_t *val;                   /* Attribute value */
   int          num_finishings,         /* Number of finishings */
                finishings[5];          /* finishings-supported values */
   int          num_qualities,          /* Number of print-quality values */
index 7c8ecabbd08f9365e00f2616cc3b8c870aa00892..41ae3b3f9f5a4cd7cf383020fa0ff4e42eecc037 100644 (file)
@@ -61,9 +61,6 @@ struct cupsd_printer_s
   time_t       state_time;             /* Time at this state */
   char         *job_sheets[2];         /* Banners/job sheets */
   cups_ptype_t type;                   /* Printer type (color, small, etc.) */
-  char         *browse_attrs;          /* Attributes sent with browse data */
-  time_t       browse_expire;          /* Expiration time for printer */
-  time_t       browse_time;            /* Last time update was sent/received */
   char         *device_uri;            /* Device URI */
   char         *sanitized_device_uri;  /* Sanitized device URI */
   char         *port_monitor;          /* Port monitor */
@@ -116,10 +113,8 @@ VAR ipp_t          *CommonData     VALUE(NULL);
                                        /* Common printer object attrs */
 VAR cups_array_t       *CommonDefaults VALUE(NULL);
                                        /* Common -default option names */
-VAR cups_array_t       *Printers       VALUE(NULL),
+VAR cups_array_t       *Printers       VALUE(NULL);
                                        /* Printer list */
-                       *ImplicitPrinters VALUE(NULL);
-                                       /* Implicit class printers */
 VAR cupsd_printer_t    *DefaultPrinter VALUE(NULL);
                                        /* Default printer */
 VAR char               *DefaultPolicy  VALUE(NULL);
index da98ffaa1833fbaff54e50878ea320045f4f33ea..454a898f519b52cad8ce64ed5d3282dee996a69e 100644 (file)
@@ -56,7 +56,6 @@ cupsdStartServer(void)
 
   cupsdStartListening();
   cupsdStartBrowsing();
-  cupsdStartPolling();
 
  /*
   * Create a pipe for CGI processes...
@@ -100,7 +99,6 @@ cupsdStopServer(void)
 
   cupsdCloseAllClients();
   cupsdStopListening();
-  cupsdStopPolling();
   cupsdStopBrowsing();
   cupsdStopAllNotifiers();
   cupsdDeleteAllCerts();
index 0bab7172781c583f93c505b66650bce2708ea762..c57d6e4fb5012bdcd4793ece7245c37bb8ce7723 100644 (file)
@@ -87,9 +87,6 @@ cupsdCleanDirty(void)
   if (DirtyFiles & CUPSD_DIRTY_CLASSES)
     cupsdSaveAllClasses();
 
-  if (DirtyFiles & CUPSD_DIRTY_REMOTE)
-    cupsdSaveRemoteCache();
-
   if (DirtyFiles & CUPSD_DIRTY_PRINTCAP)
     cupsdWritePrintcap();
 
@@ -123,10 +120,9 @@ cupsdCleanDirty(void)
 void
 cupsdMarkDirty(int what)               /* I - What file(s) are dirty? */
 {
-  cupsdLogMessage(CUPSD_LOG_DEBUG, "cupsdMarkDirty(%c%c%c%c%c%c)",
+  cupsdLogMessage(CUPSD_LOG_DEBUG, "cupsdMarkDirty(%c%c%c%c%c)",
                  (what & CUPSD_DIRTY_PRINTERS) ? 'P' : '-',
                  (what & CUPSD_DIRTY_CLASSES) ? 'C' : '-',
-                 (what & CUPSD_DIRTY_REMOTE) ? 'R' : '-',
                  (what & CUPSD_DIRTY_PRINTCAP) ? 'p' : '-',
                  (what & CUPSD_DIRTY_JOBS) ? 'J' : '-',
                  (what & CUPSD_DIRTY_SUBSCRIPTIONS) ? 'S' : '-');
@@ -266,8 +262,8 @@ cupsdSetBusyState(void)
 #  define SYSEVENT_NAMECHANGED 0x10    /* Computer name changed */
 
 
-/* 
- * Structures... 
+/*
+ * Structures...
  */
 
 typedef struct cupsd_sysevent_s                /*** System event data ****/
@@ -286,14 +282,14 @@ typedef struct cupsd_thread_data_s        /*** Thread context data  ****/
 } cupsd_thread_data_t;
 
 
-/* 
- * Local globals... 
+/*
+ * Local globals...
  */
 
 static pthread_t       SysEventThread = NULL;
                                        /* Thread to host a runloop */
 static pthread_mutex_t SysEventThreadMutex = { 0 };
-                                       /* Coordinates access to shared gloabals */ 
+                                       /* Coordinates access to shared gloabals */
 static pthread_cond_t  SysEventThreadCond = { 0 };
                                        /* Thread initialization complete condition */
 static CFRunLoopRef    SysEventRunloop = NULL;
@@ -316,8 +312,8 @@ static CFStringRef  ComputerNameKey = NULL,
 static cupsd_sysevent_t        LastSysEvent;   /* Last system event (for delayed sleep) */
 
 
-/* 
- * Local functions... 
+/*
+ * Local functions...
  */
 
 static void    *sysEventThreadEntry(void);
@@ -499,8 +495,8 @@ sysEventThreadEntry(void)
                                                   kSCEntNetIPv6);
 
   if (!NetworkGlobalKeyDNS)
-    NetworkGlobalKeyDNS = 
-       SCDynamicStoreKeyCreateNetworkGlobalEntity(kCFAllocatorDefault, 
+    NetworkGlobalKeyDNS =
+       SCDynamicStoreKeyCreateNetworkGlobalEntity(kCFAllocatorDefault,
                                                   kSCDynamicStoreDomainState,
                                                   kSCEntNetDNS);
 
@@ -582,7 +578,7 @@ sysEventThreadEntry(void)
 
   threadData.timerRef =
       CFRunLoopTimerCreate(kCFAllocatorDefault,
-                           CFAbsoluteTimeGetCurrent() + (86400L * 365L * 10L), 
+                           CFAbsoluteTimeGetCurrent() + (86400L * 365L * 10L),
                           86400L * 365L * 10L, 0, 0, sysEventTimerNotifier,
                           &timerContext);
   CFRunLoopAddTimer(CFRunLoopGetCurrent(), threadData.timerRef,
@@ -674,7 +670,7 @@ sysEventPowerNotifier(
        break;
 
     case kIOMessageSystemHasPoweredOn:
-       /* 
+       /*
        * Because powered on is followed by a net-changed event, delay
        * before sending it.
        */
@@ -702,7 +698,7 @@ sysEventPowerNotifier(
 
     if (sendit == 1)
     {
-     /* 
+     /*
       * Send the event to the main thread now.
       */
 
@@ -712,7 +708,7 @@ sysEventPowerNotifier(
     }
     else
     {
-     /* 
+     /*
       * Send the event to the main thread after 1 to 2 seconds.
       */
 
@@ -738,7 +734,7 @@ sysEventConfigurationNotifier(
 
 
   threadData = (cupsd_thread_data_t *)context;
-  
+
   (void)store;                         /* anti-compiler-warning-code */
 
   CFRange range = CFRangeMake(0, CFArrayGetCount(changedKeys));
@@ -758,12 +754,12 @@ sysEventConfigurationNotifier(
   }
 
  /*
-  * Because we registered for several different kinds of change notifications 
-  * this callback usually gets called several times in a row. We use a timer to 
+  * Because we registered for several different kinds of change notifications
+  * this callback usually gets called several times in a row. We use a timer to
   * de-bounce these so we only end up generating one event for the main thread.
   */
 
-  CFRunLoopTimerSetNextFireDate(threadData->timerRef, 
+  CFRunLoopTimerSetNextFireDate(threadData->timerRef,
                                CFAbsoluteTimeGetCurrent() + 5);
 }
 
@@ -865,20 +861,9 @@ sysUpdate(void)
            p;
           p = (cupsd_printer_t *)cupsArrayNext(Printers))
       {
-       if (p->type & CUPS_PRINTER_DISCOVERED)
-       {
-         cupsdLogMessage(CUPSD_LOG_DEBUG,
-                         "Deleting remote destination \"%s\"", p->name);
-         cupsArraySave(Printers);
-         cupsdDeletePrinter(p, 0);
-         cupsArrayRestore(Printers);
-       }
-       else
-       {
-         cupsdLogMessage(CUPSD_LOG_DEBUG,
-                         "Deregistering local printer \"%s\"", p->name);
-         cupsdDeregisterPrinter(p, 0);
-       }
+       cupsdLogMessage(CUPSD_LOG_DEBUG,
+                       "Deregistering local printer \"%s\"", p->name);
+       cupsdDeregisterPrinter(p, 0);
       }
 
       cupsdCleanDirty();
@@ -950,23 +935,8 @@ sysUpdate(void)
     if (sysevent.event & SYSEVENT_NETCHANGED)
     {
       if (!Sleeping)
-      {
         cupsdLogMessage(CUPSD_LOG_DEBUG,
                        "System network configuration changed");
-
-       /*
-        * Resetting browse_time before calling cupsdSendBrowseList causes
-       * browse packets to be sent for local shared printers.
-        */
-
-       for (p = (cupsd_printer_t *)cupsArrayFirst(Printers);
-            p;
-            p = (cupsd_printer_t *)cupsArrayNext(Printers))
-         p->browse_time = 0;
-
-        cupsdSendBrowseList();
-       cupsdRestartPolling();
-      }
       else
         cupsdLogMessage(CUPSD_LOG_DEBUG,
                        "System network configuration changed; "
@@ -1002,10 +972,7 @@ sysUpdate(void)
        for (p = (cupsd_printer_t *)cupsArrayFirst(Printers);
             p;
             p = (cupsd_printer_t *)cupsArrayNext(Printers))
-       {
-         p->browse_time = 0;
          cupsdRegisterPrinter(p);
-       }
       }
       else
         cupsdLogMessage(CUPSD_LOG_DEBUG,
index 0983f109dcde0a0555e830d2413a651953e0580a..d1672bf32cebef6d9fc95855b281a50310afa03b 100644 (file)
@@ -3,7 +3,7 @@
  *
  *   System management definitions for the CUPS scheduler.
  *
- *   Copyright 2007-2010 by Apple Inc.
+ *   Copyright 2007-2011 by Apple Inc.
  *   Copyright 2006 by Easy Software Products.
  *
  *   These coded instructions, statements, and computer programs are the
 #define CUPSD_DIRTY_NONE       0       /* Nothing is dirty */
 #define CUPSD_DIRTY_PRINTERS   1       /* printers.conf is dirty */
 #define CUPSD_DIRTY_CLASSES    2       /* classes.conf is dirty */
-#define CUPSD_DIRTY_REMOTE     4       /* remote.cache is dirty */
-#define CUPSD_DIRTY_PRINTCAP   8       /* printcap is dirty */
-#define CUPSD_DIRTY_JOBS       16      /* jobs.cache or "c" file(s) are dirty */
-#define CUPSD_DIRTY_SUBSCRIPTIONS 32   /* subscriptions.conf is dirty */
+#define CUPSD_DIRTY_PRINTCAP   4       /* printcap is dirty */
+#define CUPSD_DIRTY_JOBS       8       /* jobs.cache or "c" file(s) are dirty */
+#define CUPSD_DIRTY_SUBSCRIPTIONS 16   /* subscriptions.conf is dirty */
+
 
 /*
  * Globals...
diff --git a/scheduler/testdirsvc.c b/scheduler/testdirsvc.c
deleted file mode 100644 (file)
index 88046a9..0000000
+++ /dev/null
@@ -1,324 +0,0 @@
-/*
- * "$Id: testdirsvc.c 6649 2007-07-11 21:46:42Z mike $"
- *
- *   Browsing test program for CUPS.
- *
- *   Copyright 2007-2011 by Apple Inc.
- *   Copyright 1997-2007 by Easy Software Products, all rights reserved.
- *
- *   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
- *   file is missing or damaged, see the license at "http://www.cups.org/".
- *
- * Contents:
- *
- *   main()  - Simulate one or more remote printers.
- *   usage() - Show program usage...
- */
-
-/*
- * Include necessary headers...
- */
-
-#include <cups/cups.h>
-#include <cups/string-private.h>
-
-
-/*
- * Local functions...
- */
-
-static void    usage(void) __attribute__((noreturn));
-
-
-/*
- * 'main()' - Simulate one or more remote printers.
- */
-
-int                                    /* O - Exit status */
-main(int  argc,                                /* I - Number of command-line arguments */
-     char *argv[])                     /* I - Command-line arguments */
-{
-  int          i,                      /* Looping var */
-               printer,                /* Current printer */
-               num_printers,           /* Number of printers */
-               pclass,                 /* Current printer class */
-               num_pclasses,           /* Number of printer classes */
-               server,                 /* Current server */
-               num_servers,            /* Number of servers */
-               count,                  /* Number of printers sent this cycle */
-               interval,               /* Browse Interval */
-               lease,                  /* Browse lease-duration */
-               continuous,             /* Run continuously? */
-               port,                   /* Browse port */
-               sock,                   /* Browse socket */
-               val,                    /* Socket option value */
-               seconds,                /* Seconds until next cycle */
-               verbose;                /* Verbose output? */
-  const char   *options;               /* Options for URIs */
-  time_t       curtime;                /* Current UNIX time */
-  struct tm    *curdate;               /* Current date and time */
-  struct sockaddr_in addr;             /* Broadcast address */
-  char         packet[1540];           /* Data packet */
-  static const char * const names[26] =        /* Printer names */
-               {
-                 "alpha",
-                 "bravo",
-                 "charlie",
-                 "delta",
-                 "echo",
-                 "foxtrot",
-                 "golf",
-                 "hotel",
-                 "india",
-                 "juliet",
-                 "kilo",
-                 "lima",
-                 "mike",
-                 "november",
-                 "oscar",
-                 "papa",
-                 "quebec",
-                 "romeo",
-                 "sierra",
-                 "tango",
-                 "uniform",
-                 "victor",
-                 "wiskey",
-                 "x-ray",
-                 "yankee",
-                 "zulu"
-               };
-
-
- /*
-  * Process command-line arguments...
-  */
-
-  num_printers = 10;
-  num_pclasses = 5;
-  num_servers  = 1;
-  interval     = 30;
-  lease        = 60;
-  port         = 0;
-  verbose      = 0;
-  continuous   = 0;
-  options      = NULL;
-
-  for (i = 1; i < argc; i ++)
-  {
-    if (!strcmp(argv[i], "-c"))
-      continuous = 1;
-    else if (!strcmp(argv[i], "-i"))
-    {
-      i ++;
-      if (i < argc)
-        interval = atoi(argv[i]);
-      else
-        usage();
-
-      continuous = 1;
-    }
-    else if (!strcmp(argv[i], "-l"))
-    {
-      i ++;
-      if (i < argc)
-        lease = atoi(argv[i]);
-      else
-        usage();
-    }
-    else if (!strcmp(argv[i], "-o"))
-    {
-      i ++;
-      if (i < argc)
-        options = argv[i];
-      else
-        usage();
-    }
-    else if (!strcmp(argv[i], "-C"))
-    {
-      i ++;
-      if (i < argc)
-        num_pclasses = atoi(argv[i]);
-      else
-        usage();
-    }
-    else if (!strcmp(argv[i], "-p"))
-    {
-      i ++;
-      if (i < argc)
-        num_printers = atoi(argv[i]);
-      else
-        usage();
-    }
-    else if (!strcmp(argv[i], "-s"))
-    {
-      i ++;
-      if (i < argc)
-        num_servers = atoi(argv[i]);
-      else
-        usage();
-    }
-    else if (!strcmp(argv[i], "-v"))
-      verbose = 1;
-    else if (isdigit(argv[i][0] & 255))
-    {
-      port = atoi(argv[i]);
-    }
-    else
-      usage();
-  }
-
-  if ((num_printers <= 0 && num_pclasses <= 0) || num_servers <= 0 ||
-      interval <= 0 || lease < 1 || port <= 0)
-    usage();
-
- /*
-  * Open a broadcast socket...
-  */
-
-  if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
-  {
-    perror("Unable to open broadcast socket");
-    return (1);
-  }
-
- /*
-  * Set the "broadcast" flag...
-  */
-
-  val = 1;
-  if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &val, sizeof(val)))
-  {
-    perror("Unable to put socket in broadcast mode");
-
-    close(sock);
-    return (1);
-  }
-
- /*
-  * Broadcast to 127.0.0.1 (localhost)
-  */
-
-  memset(&addr, 0, sizeof(addr));
-  addr.sin_addr.s_addr = htonl(0x7f000001);
-  addr.sin_family      = AF_INET;
-  addr.sin_port        = htons(port);
-
- /*
-  * Send virtual printers continuously until we are stopped.
-  */
-
-  for (;;)
-  {
-   /*
-    * Start a new cycle of N printers...
-    */
-
-    printf("Sending %d printers from %d servers...\n", num_printers,
-           num_servers);
-
-    count   = num_servers * (num_printers + num_pclasses) / interval + 1;
-    curtime = time(NULL);
-    curdate = localtime(&curtime);
-    seconds = interval;
-
-    for (i = 0, printer = 0; printer < num_printers; printer ++)
-    {
-      for (server = 0; server < num_servers; server ++, i ++)
-      {
-        if (i == count)
-       {
-         seconds --;
-         i = 0;
-         sleep(1);
-         curtime = time(NULL);
-         curdate = localtime(&curtime);
-       }
-
-        snprintf(packet, sizeof(packet),
-                "%x %x ipp://testserver-%d/printers/%s-%d \"Server Room %d\" "
-                "\"Test Printer %d\" \"Acme Blazer 2000\"%s%s "
-                "lease-duration=%d\n",
-                 CUPS_PRINTER_REMOTE, IPP_PRINTER_IDLE, server + 1,
-                names[printer % 26], printer / 26 + 1, server + 1,
-                printer + 1, options ? " ipp-options=" : "",
-                options ? options : "", lease);
-
-        if (verbose)
-         printf("[%02d:%02d:%02d] %s", curdate->tm_hour, curdate->tm_min,
-                curdate->tm_sec, packet);
-
-        if (sendto(sock, packet, strlen(packet), 0,
-                  (struct sockaddr *)&addr, sizeof(addr)) < 0)
-         perror("Unabled to send packet");
-      }
-    }
-
-
-    for (i = 0, pclass = 0; pclass < num_pclasses; pclass ++)
-    {
-      for (server = 0; server < num_servers; server ++, i ++)
-      {
-        if (i == count)
-       {
-         seconds --;
-         i = 0;
-         sleep(1);
-         curtime = time(NULL);
-         curdate = localtime(&curtime);
-       }
-
-        snprintf(packet, sizeof(packet),
-                "%x %x ipp://testserver-%d/classes/class-%s-%d \"Server Room %d\" "
-                "\"Test Class %d\" \"Acme Blazer 2000\"%s%s "
-                "lease-duration=%d\n",
-                 CUPS_PRINTER_REMOTE | CUPS_PRINTER_CLASS, IPP_PRINTER_IDLE,
-                server + 1, names[pclass % 26], pclass / 26 + 1, server + 1,
-                pclass + 1, options ? " ipp-options=" : "",
-                options ? options : "", lease);
-
-        if (verbose)
-         printf("[%02d:%02d:%02d] %s", curdate->tm_hour, curdate->tm_min,
-                curdate->tm_sec, packet);
-
-        if (sendto(sock, packet, strlen(packet), 0,
-                  (struct sockaddr *)&addr, sizeof(addr)) < 0)
-         perror("Unabled to send packet");
-      }
-    }
-
-    if (!continuous)
-      break;
-
-   /*
-    * Sleep for any remaining time...
-    */
-
-    if (seconds > 0)
-      sleep(seconds);
-  }
-
-  return (0);
-}
-
-
-/*
- * 'usage()' - Show program usage...
- */
-
-static void
-usage(void)
-{
-  puts("Usage: testdirsvc [-c] [-i interval] [-l lease-duration] "
-       "[-o ipp-options] [-p printers] "
-       "[-C classes] [-s servers] [-v] port");
-  exit(0);
-}
-
-
-/*
- * End of "$Id: testdirsvc.c 6649 2007-07-11 21:46:42Z mike $".
- */
index 8726774cb3f2ae5234557090210f82110123d6be..36e161507f22e1f585c93ab01166dac9f5f5d3a7 100644 (file)
@@ -3,7 +3,7 @@
  *
  *   Scheduler notification tester for CUPS.
  *
- *   Copyright 2007-2010 by Apple Inc.
+ *   Copyright 2007-2011 by Apple Inc.
  *   Copyright 2006-2007 by Easy Software Products.
  *
  *   These coded instructions, statements, and computer programs are the
@@ -28,6 +28,7 @@
 #include <cups/debug-private.h>
 #include <cups/string-private.h>
 #include <signal.h>
+#include <cups/ipp-private.h>  /* TODO: Update so we don't need this */
 
 
 /*
@@ -302,7 +303,7 @@ print_attributes(ipp_t *ipp,                /* I - IPP request */
   int                  i;              /* Looping var */
   ipp_tag_t            group;          /* Current group */
   ipp_attribute_t      *attr;          /* Current attribute */
-  ipp_value_t          *val;           /* Current value */
+  _ipp_value_t         *val;           /* Current value */
   static const char * const tags[] =   /* Value/group tag strings */
                        {
                          "reserved-00",
index e53a7147756ddb334b24a5fc5b374ea4ff66f07f..e65a4f77b092bad44d5351fa84b9cc4d35f5c49a 100644 (file)
@@ -83,12 +83,6 @@ main(int  argc,                              /* I - Number of command-line args */
         else if (!strcmp(argv[i], "--no-remote-any"))
          num_settings = cupsAddOption(CUPS_SERVER_REMOTE_ANY, "0",
                                       num_settings, &settings);
-        else if (!strcmp(argv[i], "--remote-printers"))
-         num_settings = cupsAddOption(CUPS_SERVER_REMOTE_PRINTERS, "1",
-                                      num_settings, &settings);
-        else if (!strcmp(argv[i], "--no-remote-printers"))
-         num_settings = cupsAddOption(CUPS_SERVER_REMOTE_PRINTERS, "0",
-                                      num_settings, &settings);
         else if (!strcmp(argv[i], "--share-printers"))
          num_settings = cupsAddOption(CUPS_SERVER_SHARE_PRINTERS, "1",
                                       num_settings, &settings);
@@ -219,8 +213,6 @@ usage(const char *opt)                      /* I - Option character/string */
                           "administration on/off."));
   _cupsLangPuts(stdout, _("  --[no-]remote-any       Allow/prevent access "
                           "from the Internet."));
-  _cupsLangPuts(stdout, _("  --[no-]remote-printers  Show/hide remote "
-                          "printers."));
   _cupsLangPuts(stdout, _("  --[no-]share-printers   Turn printer sharing "
                           "on/off."));
   _cupsLangPuts(stdout, _("  --[no-]user-cancel-any  Allow/prevent users to "
index 64c3f84e9a53efca53b83190b2c41fb00e7dbf77..5fe0b9bbc9167a79ca453f2056944c5f6cd49b13 100644 (file)
@@ -1090,8 +1090,7 @@ delete_printer_option(http_t *http,       /* I - Server connection */
   *    option with deleteAttr tag
   */
 
-  if (get_printer_type(http, printer, uri, sizeof(uri)) &
-          (CUPS_PRINTER_CLASS | CUPS_PRINTER_IMPLICIT))
+  if (get_printer_type(http, printer, uri, sizeof(uri)) & CUPS_PRINTER_CLASS)
     request = ippNewRequest(CUPS_ADD_MODIFY_CLASS);
   else
     request = ippNewRequest(CUPS_ADD_MODIFY_PRINTER);
@@ -1145,8 +1144,7 @@ enable_printer(http_t *http,              /* I - Server connection */
   *    printer-is-accepting-jobs
   */
 
-  if (get_printer_type(http, printer, uri, sizeof(uri)) &
-          (CUPS_PRINTER_CLASS | CUPS_PRINTER_IMPLICIT))
+  if (get_printer_type(http, printer, uri, sizeof(uri)) & CUPS_PRINTER_CLASS)
     request = ippNewRequest(CUPS_ADD_MODIFY_CLASS);
   else
     request = ippNewRequest(CUPS_ADD_MODIFY_PRINTER);
@@ -1224,7 +1222,7 @@ get_printer_type(http_t *http,            /* I - Server connection */
   {
     type = (cups_ptype_t)attr->values[0].integer;
 
-    if (type & (CUPS_PRINTER_CLASS | CUPS_PRINTER_IMPLICIT))
+    if (type & CUPS_PRINTER_CLASS)
       httpAssembleURIf(HTTP_URI_CODING_ALL, uri, urisize, "ipp", NULL,
                       "localhost", ippPort(), "/classes/%s", printer);
   }
@@ -1283,8 +1281,7 @@ set_printer_options(
   *    other options
   */
 
-  if (get_printer_type(http, printer, uri, sizeof(uri)) &
-          (CUPS_PRINTER_CLASS | CUPS_PRINTER_IMPLICIT))
+  if (get_printer_type(http, printer, uri, sizeof(uri)) & CUPS_PRINTER_CLASS)
     request = ippNewRequest(CUPS_ADD_MODIFY_CLASS);
   else
     request = ippNewRequest(CUPS_ADD_MODIFY_PRINTER);
index eae93bba06bdb0fcd942742ce1b7ac39d8966fcf..20ef8bf005b677d593fe3471a67f9e5714a60740 100644 (file)
@@ -580,6 +580,9 @@ match_list(const char *list,                /* I - List of names */
   if (!list || !*list)
     return (1);
 
+  if (!name)
+    return (0);
+
   while (*list)
   {
    /*
index 477da139edc4581118a6896b20a7f83e530d8002..c76eb9c5eba5b0c68f7a1bc25926845929dd07bc 100644 (file)
 <P><A HREF="/admin/">Advanced <SMALL>&#x25bc;</SMALL></A><BR>
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="config-server">
 <INPUT TYPE="HIDDEN" NAME="ADVANCEDSETTINGS" VALUE="YES">
-<INPUT TYPE="CHECKBOX" NAME="REMOTE_PRINTERS" {?remote_printers}> Show printers shared by other systems<BR>
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Protocols\:
-<INPUT TYPE="CHECKBOX" NAME="BROWSE_REMOTE_CUPS" {?browse_remote_cups}> CUPS
-{HAVE_LDAP?<INPUT TYPE="CHECKBOX" NAME="BROWSE_REMOTE_LDAP" {?browse_remote_ldap}> LDAP:}
-{HAVE_LIBSLP?<INPUT TYPE="CHECKBOX" NAME="BROWSE_REMOTE_SLP" {?browse_remote_slp}> SLP:}<BR>
 <INPUT TYPE="CHECKBOX" NAME="SHARE_PRINTERS" {?share_printers}> Share printers connected to this system<BR>
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Max clients\:
 <INPUT TYPE="TEXT" NAME="MAX_CLIENTS" VALUE="{?max_clients}" SIZE="6"><BR>
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Protocols\:
-<INPUT TYPE="CHECKBOX" NAME="BROWSE_LOCAL_CUPS" {?browse_local_cups}> CUPS
-{HAVE_DNSSD?<INPUT TYPE="CHECKBOX" NAME="BROWSE_LOCAL_DNSSD" {?browse_local_dnssd}> DNS-SD:}
-{HAVE_LDAP?<INPUT TYPE="CHECKBOX" NAME="BROWSE_LOCAL_LDAP" {?browse_local_ldap}> LDAP:}
-{HAVE_LIBSLP?<INPUT TYPE="CHECKBOX" NAME="BROWSE_LOCAL_SLP" {?browse_local_slp}> SLP:}<BR>
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<INPUT TYPE="CHECKBOX" NAME="REMOTE_ANY" {?remote_any}> Allow printing from the Internet<BR>
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<INPUT TYPE="CHECKBOX" NAME="BROWSE_WEB_IF" {?browse_web_if}> Advertise web interface<BR>
 <INPUT TYPE="CHECKBOX" NAME="REMOTE_ADMIN" {?remote_admin}> Allow remote administration<BR>
@@ -75,7 +65,6 @@
 
 <P><A HREF="/admin/?ADVANCEDSETTINGS=YES">Advanced <SMALL>&#x25b6;</SMALL></A><BR>
 <INPUT TYPE="HIDDEN" NAME="OP" VALUE="config-server">
-<INPUT TYPE="CHECKBOX" NAME="REMOTE_PRINTERS" {?remote_printers}> Show printers shared by other systems<BR>
 <INPUT TYPE="CHECKBOX" NAME="SHARE_PRINTERS" {?share_printers}> Share printers connected to this system<BR>
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<INPUT TYPE="CHECKBOX" NAME="REMOTE_ANY" {?remote_any}> Allow printing from the Internet<BR>
 <INPUT TYPE="CHECKBOX" NAME="REMOTE_ADMIN" {?remote_admin}> Allow remote administration<BR>
index a21980ea6a4553a0d1182df178df6cc308df8d42..6dfd6f50e85031803a1cd966e6f4cd42807f0e9e 100644 (file)
@@ -17,7 +17,7 @@
 echo "Add Printer Test"
 echo ""
 echo "    lpadmin -p Test3 -v file:/dev/null -E -m drv:///sample.drv/deskjet.ppd"
-../systemv/lpadmin -p Test3 -v file:/dev/null -E -m drv:///sample.drv/deskjet.ppd 2>&1
+$VALGRIND ../systemv/lpadmin -p Test3 -v file:/dev/null -E -m drv:///sample.drv/deskjet.ppd 2>&1
 if test $? != 0; then
        echo "    FAILED"
        exit 1
@@ -29,7 +29,7 @@ echo ""
 echo "Modify Printer Test"
 echo ""
 echo "    lpadmin -p Test3 -v file:/tmp/Test3 -o PageSize=A4"
-../systemv/lpadmin -p Test3 -v file:/tmp/Test3 -o PageSize=A4 2>&1
+$VALGRIND ../systemv/lpadmin -p Test3 -v file:/tmp/Test3 -o PageSize=A4 2>&1
 if test $? != 0; then
        echo "    FAILED"
        exit 1
@@ -41,7 +41,7 @@ echo ""
 echo "Delete Printer Test"
 echo ""
 echo "    lpadmin -x Test3"
-../systemv/lpadmin -x Test3 2>&1
+$VALGRIND ../systemv/lpadmin -x Test3 2>&1
 if test $? != 0; then
        echo "    FAILED"
        exit 1
index b6908052cf7677253b8028c8108cece464b9599b..ff15a8715192f77043f0a9f07027117d3056b642 100644 (file)
@@ -17,7 +17,7 @@
 echo "LPC Test"
 echo ""
 echo "    lpc status"
-../berkeley/lpc status 2>&1
+$VALGRIND ../berkeley/lpc status 2>&1
 if test $? != 0; then
        echo "    FAILED"
        exit 1
index cff0a5597f4058fcbc4852b045c284fba30d50ce..633508c5a77af0ce281606a4b7d4bb2b71c26c7a 100644 (file)
@@ -17,7 +17,7 @@
 echo "LPQ Test"
 echo ""
 echo "    lpq -P Test1"
-../berkeley/lpq -P Test1 2>&1
+$VALGRIND ../berkeley/lpq -P Test1 2>&1
 if test $? != 0; then
        echo "    FAILED"
        exit 1
index 4b34d11ddc69a68aa5f8ca4a736663919b015351..b2e38f12e97b4d590575fbe02f82823e6c8992d7 100644 (file)
@@ -4,7 +4,7 @@
 #
 #   Test the lpstat command.
 #
-#   Copyright 2007-2009 by Apple Inc.
+#   Copyright 2007-2011 by Apple Inc.
 #   Copyright 1997-2005 by Easy Software Products, all rights reserved.
 #
 #   These coded instructions, statements, and computer programs are the
@@ -17,7 +17,7 @@
 echo "LPSTAT Test"
 echo ""
 echo "    lpstat -t"
-../systemv/lpstat -t 2>&1
+$VALGRIND ../systemv/lpstat -t 2>&1
 if test $? != 0; then
        echo "    FAILED"
        exit 1
@@ -29,7 +29,7 @@ echo ""
 echo "LPSTAT Test"
 echo ""
 echo "    lpstat -H"
-server="`../systemv/lpstat -H 2>&1`"
+server="`$VALGRIND ../systemv/lpstat -H 2>&1`"
 if test $? != 0 -o "x$server" != xlocalhost:8631; then
        echo "    FAILED ($server)"
        exit 1
index 9dd1dd0015a22bb09deb3e468a16a42af11d40b8..f74e79ba91dce8b9a19ae9210e1929bda6d23c42 100644 (file)
@@ -4,7 +4,7 @@
 #
 #   Test the lp command.
 #
-#   Copyright 2007-2009 by Apple Inc.
+#   Copyright 2007-2011 by Apple Inc.
 #   Copyright 1997-2005 by Easy Software Products, all rights reserved.
 #
 #   These coded instructions, statements, and computer programs are the
@@ -17,7 +17,7 @@
 echo "LP Default Test"
 echo ""
 echo "    lp testfile.pdf"
-../systemv/lp testfile.pdf 2>&1
+$VALGRIND ../systemv/lp testfile.pdf 2>&1
 if test $? != 0; then
        echo "    FAILED"
        exit 1
@@ -29,7 +29,7 @@ echo ""
 echo "LP Destination Test"
 echo ""
 echo "    lp -d Test2 testfile.jpg"
-../systemv/lp -d Test2 testfile.jpg 2>&1
+$VALGRIND ../systemv/lp -d Test2 testfile.jpg 2>&1
 if test $? != 0; then
        echo "    FAILED"
        exit 1
@@ -41,7 +41,7 @@ echo ""
 echo "LP Options Test"
 echo ""
 echo "    lp -d Test1 -P 1-4 -o job-sheets=classified,classified testfile.pdf"
-../systemv/lp -d Test1 -P 1-4 -o job-sheets=classified,classified testfile.pdf 2>&1
+$VALGRIND ../systemv/lp -d Test1 -P 1-4 -o job-sheets=classified,classified testfile.pdf 2>&1
 if test $? != 0; then
        echo "    FAILED"
        exit 1
@@ -56,16 +56,14 @@ echo "    lp -d Test1 testfile.jpg"
 echo "    lp -d Test2 testfile.jpg"
 i=0
 while test $i -lt $1; do
-       echo "    flood copy $i..." 1>&2
-
        j=1
        while test $j -le $2; do
-               ../systemv/lp -d test-$j testfile.jpg 2>&1
+               $VALGRIND ../systemv/lp -d test-$j testfile.jpg 2>&1
                j=`expr $j + 1`
        done
 
-       ../systemv/lp -d Test1 testfile.jpg 2>&1 &
-       ../systemv/lp -d Test2 testfile.jpg 2>&1 &
+       $VALGRIND ../systemv/lp -d Test1 testfile.jpg 2>&1 &
+       $VALGRIND ../systemv/lp -d Test2 testfile.jpg 2>&1 &
        lppid=$!
 
        i=`expr $i + 1`
index 72c757106216a2d0a7bce994794712a2e37e4300..17646aa88431b116304ad167e967a7932197a045 100644 (file)
@@ -4,7 +4,7 @@
 #
 #   Test the lpr command.
 #
-#   Copyright 2007-2009 by Apple Inc.
+#   Copyright 2007-2011 by Apple Inc.
 #   Copyright 1997-2005 by Easy Software Products, all rights reserved.
 #
 #   These coded instructions, statements, and computer programs are the
@@ -17,7 +17,7 @@
 echo "LPR Default Test"
 echo ""
 echo "    lpr testfile.pdf"
-../berkeley/lpr testfile.pdf 2>&1
+$VALGRIND ../berkeley/lpr testfile.pdf 2>&1
 if test $? != 0; then
        echo "    FAILED"
        exit 1
@@ -29,7 +29,7 @@ echo ""
 echo "LPR Destination Test"
 echo ""
 echo "    lpr -P Test2 testfile.jpg"
-../berkeley/lpr -P Test2 testfile.jpg 2>&1
+$VALGRIND ../berkeley/lpr -P Test2 testfile.jpg 2>&1
 if test $? != 0; then
        echo "    FAILED"
        exit 1
@@ -41,7 +41,7 @@ echo ""
 echo "LPR Options Test"
 echo ""
 echo "    lpr -P Test1 -o number-up=4 -o job-sheets=standard,none testfile.pdf"
-../berkeley/lpr -P Test1 -o number-up=4 -o job-sheets=standard,none testfile.pdf 2>&1
+$VALGRIND ../berkeley/lpr -P Test1 -o number-up=4 -o job-sheets=standard,none testfile.pdf 2>&1
 if test $? != 0; then
        echo "    FAILED"
        exit 1
@@ -56,16 +56,14 @@ echo "    lpr -P Test1 testfile.jpg"
 echo "    lpr -P Test2 testfile.jpg"
 i=0
 while test $i -lt $1; do
-       echo "    flood copy $i..." 1>&2
-
        j=1
        while test $j -le $2; do
-               ../berkeley/lpr -P test-$j testfile.jpg 2>&1
+               $VALGRIND ../berkeley/lpr -P test-$j testfile.jpg 2>&1
                j=`expr $j + 1`
        done
 
-       ../berkeley/lpr -P Test1 testfile.jpg 2>&1 &
-       ../berkeley/lpr -P Test2 testfile.jpg 2>&1 &
+       $VALGRIND ../berkeley/lpr -P Test1 testfile.jpg 2>&1 &
+       $VALGRIND ../berkeley/lpr -P Test2 testfile.jpg 2>&1 &
        lprpid=$!
 
        i=`expr $i + 1`
index bcb7211693524fd466596e443ffc4b257f818c79..4b96920bb2d816d06d0806eea72d27d77ef28997 100644 (file)
@@ -4,7 +4,7 @@
 #
 #   Test the lprm command.
 #
-#   Copyright 2007 by Apple Inc.
+#   Copyright 2007-2011 by Apple Inc.
 #   Copyright 1997-2005 by Easy Software Products, all rights reserved.
 #
 #   These coded instructions, statements, and computer programs are the
@@ -17,9 +17,9 @@
 echo "LPRM Current Test"
 echo ""
 echo "    lpr -o job-hold-until=indefinite testfile.jpg"
-../berkeley/lpr -o job-hold-until=indefinite testfile.jpg 2>&1
+$VALGRIND ../berkeley/lpr -o job-hold-until=indefinite testfile.jpg 2>&1
 echo "    lprm"
-../berkeley/lprm 2>&1
+$VALGRIND ../berkeley/lprm 2>&1
 if test $? != 0; then
        echo "    FAILED"
        exit 1
@@ -31,9 +31,9 @@ echo ""
 echo "LPRM Destination Test"
 echo ""
 echo "    lpr -P Test1 -o job-hold-until=indefinite testfile.jpg"
-../berkeley/lpr -P Test1 -o job-hold-until=indefinite testfile.jpg 2>&1
+$VALGRIND ../berkeley/lpr -P Test1 -o job-hold-until=indefinite testfile.jpg 2>&1
 echo "    lprm Test1"
-../berkeley/lprm Test1 2>&1
+$VALGRIND ../berkeley/lprm Test1 2>&1
 if test $? != 0; then
        echo "    FAILED"
        exit 1
index 7cf31b0da0505bed847375bea9e21f2dc3ab01b3..88b7dd4e2271511a9a93ea8a09fd7ddf9f989a3a 100644 (file)
@@ -4,7 +4,7 @@
 #
 #   Test the cancel command.
 #
-#   Copyright 2007-2008 by Apple Inc.
+#   Copyright 2007-2011 by Apple Inc.
 #   Copyright 1997-2006 by Easy Software Products, all rights reserved.
 #
 #   These coded instructions, statements, and computer programs are the
@@ -17,9 +17,9 @@
 echo "Cancel Destination Test"
 echo ""
 echo "    lp -d Test1 -o job-hold-until=indefinite testfile.jpg"
-../systemv/lp -d Test1 -o job-hold-until=indefinite testfile.jpg 2>&1
+$VALGRIND ../systemv/lp -d Test1 -o job-hold-until=indefinite testfile.jpg 2>&1
 echo "    cancel Test1"
-../systemv/cancel Test1 2>&1
+$VALGRIND ../systemv/cancel Test1 2>&1
 if test $? != 0; then
        echo "    FAILED"
        exit 1
@@ -31,7 +31,7 @@ echo ""
 echo "Cancel All Test"
 echo ""
 echo "    cancel -a"
-../systemv/cancel -a 2>&1
+$VALGRIND ../systemv/cancel -a 2>&1
 if test $? != 0; then
        echo "    FAILED"
        exit 1
index 1902aeb994f5a0cfe869d68c1eb0c213dbbf5e07..a6ea3645e266e47a85faa67f568d7a7a8df9fb2c 100644 (file)
@@ -4,7 +4,7 @@
 #
 #   Test the lpinfo command.
 #
-#   Copyright 2007-2008 by Apple Inc.
+#   Copyright 2007-2011 by Apple Inc.
 #   Copyright 1997-2005 by Easy Software Products, all rights reserved.
 #
 #   These coded instructions, statements, and computer programs are the
@@ -17,7 +17,7 @@
 echo "LPINFO Devices Test"
 echo ""
 echo "    lpinfo -v"
-../systemv/lpinfo -v 2>&1
+$VALGRIND ../systemv/lpinfo -v 2>&1
 if test $? != 0; then
        echo "    FAILED"
        exit 1
@@ -29,7 +29,7 @@ echo ""
 echo "LPINFO Drivers Test"
 echo ""
 echo "    lpinfo -m"
-../systemv/lpinfo -m 2>&1
+$VALGRIND ../systemv/lpinfo -m 2>&1
 if test $? != 0; then
        echo "    FAILED"
        exit 1
@@ -41,7 +41,7 @@ echo ""
 echo "LPINFO Drivers Test"
 echo ""
 echo "    lpinfo -m | grep -q sample.drv"
-../systemv/lpinfo -m | grep -q sample.drv 2>&1
+$VALGRIND ../systemv/lpinfo -m | grep -q sample.drv 2>&1
 if test $? != 0; then
        echo "    FAILED"
        exit 1
index 8e789dcb64c15800469abb992e84a37d3cf11791..749e16287da41dff02161a965811df037c081248 100644 (file)
@@ -656,6 +656,8 @@ DEFINE IPP_URI_SCHEME "/^ipps?://.+$$/"
 
 # Wait for job to complete...
 {
+       SKIP-IF-NOT-DEFINED job-id
+
        NAME "Get-Job-Attributes Until Job Complete"
        OPERATION Get-Job-Attributes
        GROUP operation-attributes-tag
index 23b4ed9701b4f63210ce68db2ee5e21efc5a7832..ec05bda54e85bb63915c79035560945361f3f347 100644 (file)
@@ -18,7 +18,6 @@
  *   main()                      - Main entry to the sample server.
  *   clean_jobs()                - Clean out old (completed) jobs.
  *   compare_jobs()              - Compare two jobs.
- *   copy_attribute()            - Copy a single attribute.
  *   copy_attributes()           - Copy attributes from one request to
  *                                 another.
  *   copy_job_attrs()            - Copy job attributes to the response.
@@ -254,8 +253,6 @@ typedef struct _ipp_client_s                /**** Client data ****/
 
 static void            clean_jobs(_ipp_printer_t *printer);
 static int             compare_jobs(_ipp_job_t *a, _ipp_job_t *b);
-static ipp_attribute_t *copy_attribute(ipp_t *to, ipp_attribute_t *attr,
-                                       ipp_tag_t group_tag, int quickcopy);
 static void            copy_attributes(ipp_t *to, ipp_t *from, cups_array_t *ra,
                                        ipp_tag_t group_tag, int quickcopy);
 static void            copy_job_attributes(_ipp_client_t *client,
@@ -576,191 +573,6 @@ compare_jobs(_ipp_job_t *a,               /* I - First job */
 }
 
 
-/*
- * 'copy_attribute()' - Copy a single attribute.
- */
-
-static ipp_attribute_t *               /* O - New attribute */
-copy_attribute(
-    ipp_t           *to,               /* O - Destination request/response */
-    ipp_attribute_t *attr,             /* I - Attribute to copy */
-    ipp_tag_t       group_tag,         /* I - Group to put the copy in */
-    int             quickcopy)         /* I - Do a quick copy? */
-{
-  int                  i;              /* Looping var */
-  ipp_attribute_t      *toattr;        /* Destination attribute */
-
-
-  if (Verbosity && attr->name)
-  {
-    char       buffer[2048];           /* Attribute value */
-
-    _ippAttrString(attr, buffer, sizeof(buffer));
-
-    fprintf(stderr, "Copying %s (%s%s) %s\n", attr->name,
-           attr->num_values > 1 ? "1setOf " : "",
-           ippTagString(attr->value_tag & ~IPP_TAG_COPY), buffer);
-  }
-
-  switch (attr->value_tag & ~IPP_TAG_COPY)
-  {
-    case IPP_TAG_ZERO :
-        toattr = ippAddSeparator(to);
-       break;
-
-    case IPP_TAG_INTEGER :
-    case IPP_TAG_ENUM :
-        toattr = ippAddIntegers(to, group_tag, attr->value_tag,
-                               attr->name, attr->num_values, NULL);
-
-        for (i = 0; i < attr->num_values; i ++)
-         toattr->values[i].integer = attr->values[i].integer;
-        break;
-
-    case IPP_TAG_BOOLEAN :
-        toattr = ippAddBooleans(to, group_tag, attr->name,
-                               attr->num_values, NULL);
-
-        for (i = 0; i < attr->num_values; i ++)
-         toattr->values[i].boolean = attr->values[i].boolean;
-        break;
-
-    case IPP_TAG_TEXT :
-    case IPP_TAG_NAME :
-    case IPP_TAG_KEYWORD :
-    case IPP_TAG_URI :
-    case IPP_TAG_URISCHEME :
-    case IPP_TAG_CHARSET :
-    case IPP_TAG_LANGUAGE :
-    case IPP_TAG_MIMETYPE :
-        toattr = ippAddStrings(to, group_tag,
-                              (ipp_tag_t)(attr->value_tag | quickcopy),
-                              attr->name, attr->num_values, NULL, NULL);
-
-        if (quickcopy)
-       {
-          for (i = 0; i < attr->num_values; i ++)
-           toattr->values[i].string.text = attr->values[i].string.text;
-        }
-       else
-       {
-          for (i = 0; i < attr->num_values; i ++)
-           toattr->values[i].string.text =
-               _cupsStrAlloc(attr->values[i].string.text);
-       }
-        break;
-
-    case IPP_TAG_DATE :
-        toattr = ippAddDate(to, group_tag, attr->name,
-                           attr->values[0].date);
-        break;
-
-    case IPP_TAG_RESOLUTION :
-        toattr = ippAddResolutions(to, group_tag, attr->name,
-                                  attr->num_values, IPP_RES_PER_INCH,
-                                  NULL, NULL);
-
-        for (i = 0; i < attr->num_values; i ++)
-       {
-         toattr->values[i].resolution.xres  = attr->values[i].resolution.xres;
-         toattr->values[i].resolution.yres  = attr->values[i].resolution.yres;
-         toattr->values[i].resolution.units = attr->values[i].resolution.units;
-       }
-        break;
-
-    case IPP_TAG_RANGE :
-        toattr = ippAddRanges(to, group_tag, attr->name,
-                             attr->num_values, NULL, NULL);
-
-        for (i = 0; i < attr->num_values; i ++)
-       {
-         toattr->values[i].range.lower = attr->values[i].range.lower;
-         toattr->values[i].range.upper = attr->values[i].range.upper;
-       }
-        break;
-
-    case IPP_TAG_TEXTLANG :
-    case IPP_TAG_NAMELANG :
-        toattr = ippAddStrings(to, group_tag,
-                              (ipp_tag_t)(attr->value_tag | quickcopy),
-                              attr->name, attr->num_values, NULL, NULL);
-
-        if (quickcopy)
-       {
-          for (i = 0; i < attr->num_values; i ++)
-         {
-            toattr->values[i].string.charset = attr->values[i].string.charset;
-           toattr->values[i].string.text    = attr->values[i].string.text;
-          }
-        }
-       else
-       {
-          for (i = 0; i < attr->num_values; i ++)
-         {
-           if (!i)
-              toattr->values[i].string.charset =
-                 _cupsStrAlloc(attr->values[i].string.charset);
-           else
-              toattr->values[i].string.charset =
-                 toattr->values[0].string.charset;
-
-           toattr->values[i].string.text =
-               _cupsStrAlloc(attr->values[i].string.text);
-          }
-        }
-        break;
-
-    case IPP_TAG_BEGIN_COLLECTION :
-        toattr = ippAddCollections(to, group_tag, attr->name,
-                                  attr->num_values, NULL);
-
-        for (i = 0; i < attr->num_values; i ++)
-       {
-         toattr->values[i].collection = attr->values[i].collection;
-         attr->values[i].collection->use ++;
-       }
-        break;
-
-    case IPP_TAG_STRING :
-        if (quickcopy)
-       {
-         toattr = ippAddOctetString(to, group_tag, attr->name, NULL, 0);
-         toattr->value_tag |= quickcopy;
-         toattr->values[0].unknown.data   = attr->values[0].unknown.data;
-         toattr->values[0].unknown.length = attr->values[0].unknown.length;
-       }
-       else
-         toattr = ippAddOctetString(to, attr->group_tag, attr->name,
-                                    attr->values[0].unknown.data,
-                                    attr->values[0].unknown.length);
-        break;
-
-    default :
-        toattr = ippAddIntegers(to, group_tag, attr->value_tag,
-                               attr->name, attr->num_values, NULL);
-
-        for (i = 0; i < attr->num_values; i ++)
-       {
-         toattr->values[i].unknown.length = attr->values[i].unknown.length;
-
-         if (toattr->values[i].unknown.length > 0)
-         {
-           if ((toattr->values[i].unknown.data =
-                    malloc(toattr->values[i].unknown.length)) == NULL)
-             toattr->values[i].unknown.length = 0;
-           else
-             memcpy(toattr->values[i].unknown.data,
-                    attr->values[i].unknown.data,
-                    toattr->values[i].unknown.length);
-         }
-       }
-        break; /* anti-compiler-warning-code */
-  }
-
-  return (toattr);
-}
-
-
 /*
  * 'copy_attributes()' - Copy attributes from one request to another.
  */
@@ -789,7 +601,7 @@ copy_attributes(ipp_t        *to,   /* I - Destination request */
       continue;
 
     if (!ra || cupsArrayFind(ra, fromattr->name))
-      copy_attribute(to, fromattr, fromattr->group_tag, quickcopy);
+      ippCopyAttribute(to, fromattr, quickcopy);
   }
 }
 
@@ -1215,7 +1027,7 @@ create_printer(const char *servername,    /* I - Server hostname (NULL for default)
                                        /* media-size-supported value */
   ipp_t                        *media_col_default;
                                        /* media-col-default value */
-  ipp_value_t          *media_col_value;
+  _ipp_value_t         *media_col_value;
                                        /* Current media-col-database value */
   int                  k_supported;    /* Maximum file size supported */
 #ifdef HAVE_STATVFS
@@ -2084,7 +1896,7 @@ debug_attributes(const char *title,       /* I - Title */
 
     if (attr->name)
     {
-      _ippAttrString(attr, buffer, sizeof(buffer));
+      ippAttributeString(attr, buffer, sizeof(buffer));
       fprintf(stderr, "    %s (%s%s) %s\n", attr->name,
              attr->num_values > 1 ? "1setOf " : "",
              ippTagString(attr->value_tag), buffer);
@@ -4978,12 +4790,16 @@ respond_unsupported(
     _ipp_client_t   *client,           /* I - Client */
     ipp_attribute_t *attr)             /* I - Atribute */
 {
+  ipp_attribute_t      *temp;          /* Copy of attribute */
+
+
   if (!client->response->attrs)
     respond_ipp(client, IPP_ATTRIBUTES, "Unsupported %s %s%s value.",
                attr->name, attr->num_values > 1 ? "1setOf " : "",
                ippTagString(attr->value_tag));
 
-  copy_attribute(client->response, attr, IPP_TAG_UNSUPPORTED_GROUP, 0);
+  temp = ippCopyAttribute(client->response, attr, 0);
+  ippSetGroupTag(client->response, &temp, IPP_TAG_UNSUPPORTED_GROUP);
 }
 
 
index 59b83253dde911b2072cdfd7061381ddb8003da2..c9060905d57b90ecf69426489436754488a21b20 100644 (file)
@@ -1146,7 +1146,7 @@ do_tests(_cups_vars_t *vars,              /* I - Variables */
 
          if ((tempcol = realloc(lastcol, sizeof(ipp_attribute_t) +
                                          (lastcol->num_values + 1) *
-                                         sizeof(ipp_value_t))) == NULL)
+                                         sizeof(_ipp_value_t))) == NULL)
          {
            print_fatal_error("Unable to allocate memory on line %d.", linenum);
            pass = 0;
@@ -1499,21 +1499,22 @@ do_tests(_cups_vars_t *vars,            /* I - Variables */
        }
 
         expand_variables(vars, token, temp, sizeof(token));
+        attrptr = NULL;
 
         switch (value)
        {
          case IPP_TAG_BOOLEAN :
              if (!_cups_strcasecmp(token, "true"))
-               ippAddBoolean(request, group, attr, 1);
+               attrptr = ippAddBoolean(request, group, attr, 1);
               else
-               ippAddBoolean(request, group, attr, atoi(token));
+               attrptr = ippAddBoolean(request, group, attr, atoi(token));
              break;
 
          case IPP_TAG_INTEGER :
          case IPP_TAG_ENUM :
              if (!strchr(token, ','))
-               ippAddInteger(request, group, value, attr,
-                             strtol(token, &tokenptr, 0));
+               attrptr = ippAddInteger(request, group, value, attr,
+                                       strtol(token, &tokenptr, 0));
              else
              {
                int     values[100],    /* Values */
@@ -1532,7 +1533,7 @@ do_tests(_cups_vars_t *vars,              /* I - Variables */
                  num_values ++;
                }
 
-               ippAddIntegers(request, group, value, attr, num_values, values);
+               attrptr = ippAddIntegers(request, group, value, attr, num_values, values);
              }
 
              if (!tokenptr || *tokenptr)
@@ -1568,14 +1569,14 @@ do_tests(_cups_vars_t *vars,            /* I - Variables */
                }
 
                if (!_cups_strcasecmp(ptr, "dpi"))
-                 ippAddResolution(request, group, attr, IPP_RES_PER_INCH,
-                                  xres, yres);
+                 attrptr = ippAddResolution(request, group, attr, IPP_RES_PER_INCH,
+                                            xres, yres);
                else if (!_cups_strcasecmp(ptr, "dpc"))
-                 ippAddResolution(request, group, attr, IPP_RES_PER_CM,
-                                  xres, yres);
+                 attrptr = ippAddResolution(request, group, attr, IPP_RES_PER_CM,
+                                            xres, yres);
                else
-                 ippAddResolution(request, group, attr, (ipp_res_t)0,
-                                  xres, yres);
+                 attrptr = ippAddResolution(request, group, attr, (ipp_res_t)0,
+                                            xres, yres);
              }
              break;
 
@@ -1600,8 +1601,8 @@ do_tests(_cups_vars_t *vars,              /* I - Variables */
                  goto test_exit;
                }
 
-               ippAddRanges(request, group, attr, num_vals / 2, lowers,
-                            uppers);
+               attrptr = ippAddRanges(request, group, attr, num_vals / 2, lowers,
+                                      uppers);
              }
              break;
 
@@ -1613,7 +1614,7 @@ do_tests(_cups_vars_t *vars,              /* I - Variables */
 
                 if (col)
                 {
-                 lastcol = ippAddCollection(request, group, attr, col);
+                 attrptr = lastcol = ippAddCollection(request, group, attr, col);
                  ippDelete(col);
                }
                else
@@ -1648,7 +1649,7 @@ do_tests(_cups_vars_t *vars,              /* I - Variables */
          case IPP_TAG_LANGUAGE :
          case IPP_TAG_MIMETYPE :
              if (!strchr(token, ','))
-               ippAddString(request, group, value, attr, NULL, token);
+               attrptr = ippAddString(request, group, value, attr, NULL, token);
              else
              {
               /*
@@ -1670,11 +1671,19 @@ do_tests(_cups_vars_t *vars,            /* I - Variables */
                  num_values ++;
                }
 
-               ippAddStrings(request, group, value, attr, num_values,
-                             NULL, (const char **)values);
+               attrptr = ippAddStrings(request, group, value, attr, num_values,
+                                       NULL, (const char **)values);
              }
              break;
        }
+
+       if (!attrptr)
+       {
+         print_fatal_error("Unable to add attribute on line %d: %s", linenum,
+                           cupsLastErrorString());
+         pass = 0;
+         goto test_exit;
+       }
       }
       else if (!_cups_strcasecmp(token, "FILE"))
       {
@@ -2327,6 +2336,9 @@ do_tests(_cups_vars_t *vars,              /* I - Variables */
 
             switch (attrptr->group_tag)
             {
+              case IPP_TAG_ZERO :
+                  break;
+
               case IPP_TAG_OPERATION :
                   prev_pass = pass = 0;
                   break;
@@ -2358,7 +2370,8 @@ do_tests(_cups_vars_t *vars,              /* I - Variables */
             if (!pass)
              break;
 
-           group = attrptr->group_tag;
+           if (attrptr->group_tag != IPP_TAG_ZERO)
+             group = attrptr->group_tag;
          }
 
          if (!validate_attr(attrptr, 0))
@@ -2434,7 +2447,7 @@ do_tests(_cups_vars_t *vars,              /* I - Variables */
          }
 
          if (found)
-           _ippAttrString(found, buffer, sizeof(buffer));
+           ippAttributeString(found, buffer, sizeof(buffer));
 
          if (found &&
              !with_value(expect->with_value, expect->with_regex, found, 0,
@@ -2535,18 +2548,19 @@ do_tests(_cups_vars_t *vars,            /* I - Variables */
     {
       puts(prev_pass ? "PASS]" : "FAIL]");
 
-      if (Verbosity && response)
+      if (!prev_pass || (Verbosity && response))
       {
        printf("        RECEIVED: %lu bytes in response\n",
               (unsigned long)ippLength(response));
-       printf("        status-code = %x (%s)\n", cupsLastError(),
-              ippErrorString(cupsLastError()));
+       printf("        status-code = %s (%s)\n", ippErrorString(cupsLastError()),
+              cupsLastErrorString());
 
-       for (attrptr = response->attrs;
-            attrptr != NULL;
-            attrptr = attrptr->next)
-       {
-         print_attr(attrptr, NULL);
+        if (response)
+        {
+         for (attrptr = response->attrs;
+              attrptr != NULL;
+              attrptr = attrptr->next)
+           print_attr(attrptr, NULL);
        }
       }
     }
@@ -2567,7 +2581,7 @@ do_tests(_cups_vars_t *vars,              /* I - Variables */
             attrptr = ippFindNextAttribute(response, displayed[i],
                                            IPP_TAG_ZERO))
        {
-         width = _ippAttrString(attrptr, NULL, 0);
+         width = ippAttributeString(attrptr, NULL, 0);
          if (width > widths[i])
            widths[i] = width;
        }
@@ -2732,6 +2746,9 @@ do_tests(_cups_vars_t *vars,              /* I - Variables */
 
             switch (attrptr->group_tag)
             {
+              case IPP_TAG_ZERO :
+                  break;
+
               case IPP_TAG_OPERATION :
                   prev_pass = pass = 0;
                   break;
@@ -2768,7 +2785,8 @@ do_tests(_cups_vars_t *vars,              /* I - Variables */
                   break;
             }
 
-           group = attrptr->group_tag;
+           if (attrptr->group_tag != IPP_TAG_ZERO)
+             group = attrptr->group_tag;
          }
 
          validate_attr(attrptr, 1);
@@ -3216,7 +3234,7 @@ get_collection(_cups_vars_t *vars,        /* I  - Variables */
 
        if ((tempcol = realloc(lastcol, sizeof(ipp_attribute_t) +
                                        (lastcol->num_values + 1) *
-                                       sizeof(ipp_value_t))) == NULL)
+                                       sizeof(_ipp_value_t))) == NULL)
        {
          print_fatal_error("Unable to allocate memory on line %d.", *linenum);
          goto col_error;
@@ -3737,14 +3755,14 @@ print_attr(ipp_attribute_t *attr,       /* I  - Attribute to print */
            if (Output == _CUPS_OUTPUT_PLIST)
            {
              fputs("<dict><key>language</key><string>", stdout);
-             print_xml_string(NULL, attr->values[i].string.charset);
+             print_xml_string(NULL, attr->values[i].string.language);
              fputs("</string><key>string</key><string>", stdout);
              print_xml_string(NULL, attr->values[i].string.text);
              puts("</string></dict>");
            }
            else
-             printf("\"%s\"(%s) ", attr->values[i].string.text,
-                    attr->values[i].string.charset);
+             printf("\"%s\"[%s] ", attr->values[i].string.text,
+                    attr->values[i].string.language);
          break;
 
       case IPP_TAG_BEGIN_COLLECTION :
@@ -3798,7 +3816,7 @@ print_attr(ipp_attribute_t *attr, /* I  - Attribute to print */
             ippTagString(attr->value_tag));
     }
 
-    _ippAttrString(attr, buffer, sizeof(buffer));
+    ippAttributeString(attr, buffer, sizeof(buffer));
     puts(buffer);
   }
 }
@@ -3870,8 +3888,8 @@ print_col(ipp_t *col)                     /* I - Collection attribute to print */
       case IPP_TAG_TEXTLANG :
       case IPP_TAG_NAMELANG :
          for (i = 0; i < attr->num_values; i ++)
-           printf("\"%s\",%s ", attr->values[i].string.text,
-                  attr->values[i].string.charset);
+           printf("\"%s\"[%s] ", attr->values[i].string.text,
+                  attr->values[i].string.language);
          break;
 
       case IPP_TAG_BEGIN_COLLECTION :
@@ -3941,7 +3959,7 @@ print_csv(
           break;
         else if (!strcmp(current->name, displayed[i]))
         {
-          _ippAttrString(current, buffer, maxlength);
+          ippAttributeString(current, buffer, maxlength);
           break;
         }
       }
@@ -4062,7 +4080,7 @@ print_line(
           break;
         else if (!strcmp(current->name, displayed[i]))
         {
-          _ippAttrString(current, buffer, maxlength);
+          ippAttributeString(current, buffer, maxlength);
           break;
         }
       }
@@ -5264,7 +5282,7 @@ with_value(char            *value,        /* I - Value string */
                  }
                  break;
              case '>' :
-                 if (attr->values[i].range.lower > intvalue)
+                 if (attr->values[i].range.upper > intvalue)
                  {
                    snprintf(matchbuf, matchlen, "%d-%d",
                             attr->values[i].range.lower,
index 255f3066db59545d44c11164bc43b9ea47902d10..147650d39805ff62e1d247e346ad09372aea1e2a 100755 (executable)
@@ -203,12 +203,17 @@ echo ""
 
 case "$usevalgrind" in
        Y* | y*)
-               valgrind="valgrind --tool=memcheck --log-file=/tmp/cups-$user/log/valgrind.%p --error-limit=no --leak-check=yes --trace-children=yes --read-var-info=yes"
+               VALGRIND="valgrind --tool=memcheck --log-file=/tmp/cups-$user/log/valgrind.%p --error-limit=no --leak-check=yes --trace-children=yes --read-var-info=yes"
+               if test `uname` = Darwin; then
+                       VALGRIND="$VALGRIND --dsymutil=yes"
+               fi
+               export VALGRIND
                echo "Using Valgrind; log files can be found in /tmp/cups-$user/log..."
                ;;
 
        *)
-               valgrind=""
+               VALGRIND=""
+               export VALGRIND
                ;;
 esac
 
@@ -235,14 +240,14 @@ case "$usedebugprintfs" in
                echo "Enabling debug printfs; log files can be found in /tmp/cups-$user/log..."
                CUPS_DEBUG_LOG="/tmp/cups-$user/log/debug_printfs.%d"; export CUPS_DEBUG_LOG
                CUPS_DEBUG_LEVEL=5; export CUPS_DEBUG_LEVEL
-               CUPS_DEBUG_FILTER='^(http|_http|ipp|_ipp|cups.*Request|cupsGetRespond|cupsSend).*$'; export CUPS_DEBUG_FILTER
+               CUPS_DEBUG_FILTER='^(http|_http|ipp|_ipp|cups.*Request|cupsGetResponse|cupsSend).*$'; export CUPS_DEBUG_FILTER
                ;;
 
        0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9)
                echo "Enabling debug printfs; log files can be found in /tmp/cups-$user/log..."
                CUPS_DEBUG_LOG="/tmp/cups-$user/log/debug_printfs.%d"; export CUPS_DEBUG_LOG
                CUPS_DEBUG_LEVEL=$usedebugprintf; export CUPS_DEBUG_LEVEL
-               CUPS_DEBUG_FILTER='^(http|_http|ipp|_ipp|cups.*Request|cupsGetRespond|cupsSend).*$'; export CUPS_DEBUG_FILTER
+               CUPS_DEBUG_FILTER='^(http|_http|ipp|_ipp|cups.*Request|cupsGetResponse|cupsSend).*$'; export CUPS_DEBUG_FILTER
                ;;
 
        *)
@@ -510,14 +515,14 @@ export LC_MESSAGES
 #
 
 echo "Starting scheduler:"
-echo "    $valgrind ../scheduler/cupsd -c /tmp/cups-$user/cupsd.conf -f >/tmp/cups-$user/log/debug_log 2>&1 &"
+echo "    $VALGRIND ../scheduler/cupsd -c /tmp/cups-$user/cupsd.conf -f >/tmp/cups-$user/log/debug_log 2>&1 &"
 echo ""
 
-if test `uname` = Darwin -a "x$valgrind" = x; then
+if test `uname` = Darwin -a "x$VALGRIND" = x; then
        DYLD_INSERT_LIBRARIES=/usr/lib/libgmalloc.dylib
        ../scheduler/cupsd -c /tmp/cups-$user/cupsd.conf -f >/tmp/cups-$user/log/debug_log 2>&1 &
 else
-       $valgrind ../scheduler/cupsd -c /tmp/cups-$user/cupsd.conf -f >/tmp/cups-$user/log/debug_log 2>&1 &
+       $VALGRIND ../scheduler/cupsd -c /tmp/cups-$user/cupsd.conf -f >/tmp/cups-$user/log/debug_log 2>&1 &
 fi
 
 cupsd=$!
@@ -601,15 +606,17 @@ echo "<PRE>" >>$strfile
 
 fail=0
 for file in 4*.test; do
-       echo "Performing $file..."
+       echo $ac_n "Performing $file: $ac_c"
        echo "" >>$strfile
 
-       ./ipptool -t ipp://localhost:$port/printers $file | tee -a $strfile
+       $VALGRIND ./ipptool -tI ipp://localhost:$port/printers $file >> $strfile
        status=$?
 
        if test $status != 0; then
-               echo Test failed.
+               echo FAIL
                fail=`expr $fail + 1`
+       else
+               echo PASS
        fi
 done
 
@@ -629,16 +636,18 @@ echo $date by $user on `hostname`. >>$strfile
 echo "<PRE>" >>$strfile
 
 for file in 5*.sh; do
-       echo "Performing $file..."
+       echo $ac_n "Performing $file: $ac_c"
        echo "" >>$strfile
        echo "\"$file\":" >>$strfile
 
-       sh $file $pjobs $pprinters | tee -a $strfile
+       sh $file $pjobs $pprinters >> $strfile
        status=$?
 
        if test $status != 0; then
-               echo Test failed.
+               echo FAIL
                fail=`expr $fail + 1`
+       else
+               echo PASS
        fi
 done
 
index 9dabb89260ea09a0f70157ba0591ee547c6500cd..45d459319e5fa1fa7a8bfe68b1a571da36779bed 100644 (file)
@@ -28,6 +28,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ipptool", "ipptool.vcproj",
                {CB4AA6F2-3E84-45BE-B505-95CD375E8BE3} = {CB4AA6F2-3E84-45BE-B505-95CD375E8BE3}\r
        EndProjectSection\r
 EndProject\r
+Project("{54435603-DBB4-11D2-8724-00A0C9A8B90C}") = "ipptool-installer", "ipptool-installer.vdproj", "{6AEA263B-92C0-426F-B5FF-F7F5917B704A}"\r
+EndProject\r
 Global\r
        GlobalSection(SolutionConfigurationPlatforms) = preSolution\r
                Debug|Win32 = Debug|Win32\r
@@ -84,6 +86,14 @@ Global
                {B246D91E-61F2-4433-BFD2-6C2A96FBD4D4}.Release|Win32.Build.0 = Release|Win32\r
                {B246D91E-61F2-4433-BFD2-6C2A96FBD4D4}.Release|x64.ActiveCfg = Release|x64\r
                {B246D91E-61F2-4433-BFD2-6C2A96FBD4D4}.Release|x64.Build.0 = Release|x64\r
+               {6AEA263B-92C0-426F-B5FF-F7F5917B704A}.Debug|Win32.ActiveCfg = Debug\r
+               {6AEA263B-92C0-426F-B5FF-F7F5917B704A}.Debug|Win32.Build.0 = Debug\r
+               {6AEA263B-92C0-426F-B5FF-F7F5917B704A}.Debug|x64.ActiveCfg = Debug\r
+               {6AEA263B-92C0-426F-B5FF-F7F5917B704A}.Debug|x64.Build.0 = Debug\r
+               {6AEA263B-92C0-426F-B5FF-F7F5917B704A}.Release|Win32.ActiveCfg = Release\r
+               {6AEA263B-92C0-426F-B5FF-F7F5917B704A}.Release|Win32.Build.0 = Release\r
+               {6AEA263B-92C0-426F-B5FF-F7F5917B704A}.Release|x64.ActiveCfg = Release\r
+               {6AEA263B-92C0-426F-B5FF-F7F5917B704A}.Release|x64.Build.0 = Release\r
        EndGlobalSection\r
        GlobalSection(SolutionProperties) = preSolution\r
                HideSolutionNode = FALSE\r
index 8c3416963010b11d647452bf37d5e975ca4e5eb9..4739f371992e5078cbc306163f4a557a35f828e9 100644 (file)
@@ -21,8 +21,8 @@
        <Configurations>\r
                <Configuration\r
                        Name="Debug|Win32"\r
-                       OutputDirectory="$(SolutionDir)$(ConfigurationName)"\r
-                       IntermediateDirectory="$(ConfigurationName)"\r
+                       OutputDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"\r
                        ConfigurationType="1"\r
                        CharacterSet="1"\r
                        >\r
                        />\r
                </Configuration>\r
                <Configuration\r
-                       Name="Release|Win32"\r
-                       OutputDirectory="$(SolutionDir)$(ConfigurationName)"\r
-                       IntermediateDirectory="$(ConfigurationName)"\r
+                       Name="Debug|x64"\r
+                       OutputDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"\r
                        ConfigurationType="1"\r
                        CharacterSet="1"\r
-                       WholeProgramOptimization="1"\r
                        >\r
                        <Tool\r
                                Name="VCPreBuildEventTool"\r
                        />\r
                        <Tool\r
                                Name="VCMIDLTool"\r
+                               TargetEnvironment="3"\r
                        />\r
                        <Tool\r
                                Name="VCCLCompilerTool"\r
+                               Optimization="0"\r
                                AdditionalIncludeDirectories="..;..\vcnet"\r
-                               PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE"\r
-                               RuntimeLibrary="2"\r
+                               PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE"\r
+                               MinimalRebuild="true"\r
+                               BasicRuntimeChecks="3"\r
+                               RuntimeLibrary="3"\r
                                UsePrecompiledHeader="0"\r
                                WarningLevel="1"\r
                                Detect64BitPortabilityProblems="false"\r
                        />\r
                        <Tool\r
                                Name="VCLinkerTool"\r
-                               LinkIncremental="1"\r
+                               LinkIncremental="2"\r
                                GenerateDebugInformation="true"\r
                                SubSystem="1"\r
-                               OptimizeReferences="2"\r
-                               EnableCOMDATFolding="2"\r
                                RandomizedBaseAddress="1"\r
                                DataExecutionPrevention="0"\r
-                               TargetMachine="1"\r
+                               TargetMachine="17"\r
                        />\r
                        <Tool\r
                                Name="VCALinkTool"\r
                        />\r
                </Configuration>\r
                <Configuration\r
-                       Name="Debug|x64"\r
-                       OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"\r
+                       Name="Release|Win32"\r
+                       OutputDirectory="$(PlatformName)\$(ConfigurationName)"\r
                        IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"\r
                        ConfigurationType="1"\r
                        CharacterSet="1"\r
+                       WholeProgramOptimization="1"\r
                        >\r
                        <Tool\r
                                Name="VCPreBuildEventTool"\r
                        />\r
                        <Tool\r
                                Name="VCMIDLTool"\r
-                               TargetEnvironment="3"\r
                        />\r
                        <Tool\r
                                Name="VCCLCompilerTool"\r
-                               Optimization="0"\r
                                AdditionalIncludeDirectories="..;..\vcnet"\r
-                               PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE"\r
-                               MinimalRebuild="true"\r
-                               BasicRuntimeChecks="3"\r
-                               RuntimeLibrary="3"\r
+                               PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE"\r
+                               RuntimeLibrary="2"\r
                                UsePrecompiledHeader="0"\r
                                WarningLevel="1"\r
                                Detect64BitPortabilityProblems="false"\r
                        />\r
                        <Tool\r
                                Name="VCLinkerTool"\r
-                               LinkIncremental="2"\r
+                               LinkIncremental="1"\r
                                GenerateDebugInformation="true"\r
                                SubSystem="1"\r
+                               OptimizeReferences="2"\r
+                               EnableCOMDATFolding="2"\r
                                RandomizedBaseAddress="1"\r
                                DataExecutionPrevention="0"\r
-                               TargetMachine="17"\r
+                               TargetMachine="1"\r
                        />\r
                        <Tool\r
                                Name="VCALinkTool"\r
                </Configuration>\r
                <Configuration\r
                        Name="Release|x64"\r
-                       OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"\r
+                       OutputDirectory="$(PlatformName)\$(ConfigurationName)"\r
                        IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"\r
                        ConfigurationType="1"\r
                        CharacterSet="1"\r
diff --git a/vcnet/ipptool-installer.vdproj b/vcnet/ipptool-installer.vdproj
new file mode 100644 (file)
index 0000000..641fabe
--- /dev/null
@@ -0,0 +1,1551 @@
+"DeployProject"\r
+{\r
+"VSVersion" = "3:800"\r
+"ProjectType" = "8:{978C614F-708E-4E1A-B201-565925725DBA}"\r
+"IsWebType" = "8:FALSE"\r
+"ProjectName" = "8:ipptool-installer"\r
+"LanguageId" = "3:1033"\r
+"CodePage" = "3:1252"\r
+"UILanguageId" = "3:1033"\r
+"SccProjectName" = "8:"\r
+"SccLocalPath" = "8:"\r
+"SccAuxPath" = "8:"\r
+"SccProvider" = "8:"\r
+    "Hierarchy"\r
+    {\r
+        "Entry"\r
+        {\r
+        "MsmKey" = "8:_009DC3ED78164048934ED35E89A0A1C5"\r
+        "OwnerKey" = "8:_UNDEFINED"\r
+        "MsmSig" = "8:_UNDEFINED"\r
+        }\r
+        "Entry"\r
+        {\r
+        "MsmKey" = "8:_08C93FB397914590906BDE7683F66B04"\r
+        "OwnerKey" = "8:_EA282F32A10B4ED1A81AA6133B997C6A"\r
+        "MsmSig" = "8:_UNDEFINED"\r
+        }\r
+        "Entry"\r
+        {\r
+        "MsmKey" = "8:_08C93FB397914590906BDE7683F66B04"\r
+        "OwnerKey" = "8:_E97571D3FBE048DABDC59B37762D800F"\r
+        "MsmSig" = "8:_UNDEFINED"\r
+        }\r
+        "Entry"\r
+        {\r
+        "MsmKey" = "8:_1A1324305D78463BBFC62269C56DCF0B"\r
+        "OwnerKey" = "8:_UNDEFINED"\r
+        "MsmSig" = "8:_UNDEFINED"\r
+        }\r
+        "Entry"\r
+        {\r
+        "MsmKey" = "8:_3251CC1E864E41D58BDE7A6F35F2407A"\r
+        "OwnerKey" = "8:_08C93FB397914590906BDE7683F66B04"\r
+        "MsmSig" = "8:_UNDEFINED"\r
+        }\r
+        "Entry"\r
+        {\r
+        "MsmKey" = "8:_40C483299484486C9416B704F0EF4A6C"\r
+        "OwnerKey" = "8:_UNDEFINED"\r
+        "MsmSig" = "8:_UNDEFINED"\r
+        }\r
+        "Entry"\r
+        {\r
+        "MsmKey" = "8:_41260853156249FDB39A8E386F935492"\r
+        "OwnerKey" = "8:_UNDEFINED"\r
+        "MsmSig" = "8:_UNDEFINED"\r
+        }\r
+        "Entry"\r
+        {\r
+        "MsmKey" = "8:_425F2537D86148B9A4233AD27D426738"\r
+        "OwnerKey" = "8:_UNDEFINED"\r
+        "MsmSig" = "8:_UNDEFINED"\r
+        }\r
+        "Entry"\r
+        {\r
+        "MsmKey" = "8:_65CBD149C9DA448FBACE2B02766A6537"\r
+        "OwnerKey" = "8:_UNDEFINED"\r
+        "MsmSig" = "8:_UNDEFINED"\r
+        }\r
+        "Entry"\r
+        {\r
+        "MsmKey" = "8:_6F893B2A3B7048CBA39359FC368BCA27"\r
+        "OwnerKey" = "8:_UNDEFINED"\r
+        "MsmSig" = "8:_UNDEFINED"\r
+        }\r
+        "Entry"\r
+        {\r
+        "MsmKey" = "8:_80DBA85C961E447CB92C95CE1F38C56B"\r
+        "OwnerKey" = "8:_UNDEFINED"\r
+        "MsmSig" = "8:_UNDEFINED"\r
+        }\r
+        "Entry"\r
+        {\r
+        "MsmKey" = "8:_842C04D73EBC4F5DBC2FD58D5B98D5D1"\r
+        "OwnerKey" = "8:_UNDEFINED"\r
+        "MsmSig" = "8:_UNDEFINED"\r
+        }\r
+        "Entry"\r
+        {\r
+        "MsmKey" = "8:_8AC6B9D7EF6B4C7A8C7B5AD85AA397C3"\r
+        "OwnerKey" = "8:_UNDEFINED"\r
+        "MsmSig" = "8:_UNDEFINED"\r
+        }\r
+        "Entry"\r
+        {\r
+        "MsmKey" = "8:_8CC3562BCDED4676A672115D19D898B5"\r
+        "OwnerKey" = "8:_UNDEFINED"\r
+        "MsmSig" = "8:_UNDEFINED"\r
+        }\r
+        "Entry"\r
+        {\r
+        "MsmKey" = "8:_9967519E7058965D4C7DEF47EB39CC50"\r
+        "OwnerKey" = "8:_EA282F32A10B4ED1A81AA6133B997C6A"\r
+        "MsmSig" = "8:_UNDEFINED"\r
+        }\r
+        "Entry"\r
+        {\r
+        "MsmKey" = "8:_9FBF78D7B89EEA843380D5F10E1954D7"\r
+        "OwnerKey" = "8:_EA282F32A10B4ED1A81AA6133B997C6A"\r
+        "MsmSig" = "8:_UNDEFINED"\r
+        }\r
+        "Entry"\r
+        {\r
+        "MsmKey" = "8:_AF057921D20E4520A3C6420F0729A744"\r
+        "OwnerKey" = "8:_UNDEFINED"\r
+        "MsmSig" = "8:_UNDEFINED"\r
+        }\r
+        "Entry"\r
+        {\r
+        "MsmKey" = "8:_B9E79062FEF64745915546DDD5BF8D85"\r
+        "OwnerKey" = "8:_UNDEFINED"\r
+        "MsmSig" = "8:_UNDEFINED"\r
+        }\r
+        "Entry"\r
+        {\r
+        "MsmKey" = "8:_C430646D6E7C4CBDA84F951AE95EB76F"\r
+        "OwnerKey" = "8:_UNDEFINED"\r
+        "MsmSig" = "8:_UNDEFINED"\r
+        }\r
+        "Entry"\r
+        {\r
+        "MsmKey" = "8:_D4BEA026ABFB46DD960AD8EFCAE45E31"\r
+        "OwnerKey" = "8:_UNDEFINED"\r
+        "MsmSig" = "8:_UNDEFINED"\r
+        }\r
+        "Entry"\r
+        {\r
+        "MsmKey" = "8:_D5CD9D9AB1644688A1D54B1589BDF724"\r
+        "OwnerKey" = "8:_UNDEFINED"\r
+        "MsmSig" = "8:_UNDEFINED"\r
+        }\r
+        "Entry"\r
+        {\r
+        "MsmKey" = "8:_E30823E684384F4DB7385B14F714AD95"\r
+        "OwnerKey" = "8:_UNDEFINED"\r
+        "MsmSig" = "8:_UNDEFINED"\r
+        }\r
+        "Entry"\r
+        {\r
+        "MsmKey" = "8:_E3C6C5A7FDD94965B68960844461D5EA"\r
+        "OwnerKey" = "8:_UNDEFINED"\r
+        "MsmSig" = "8:_UNDEFINED"\r
+        }\r
+        "Entry"\r
+        {\r
+        "MsmKey" = "8:_E4C0F67094B94E05AB69787080727089"\r
+        "OwnerKey" = "8:_UNDEFINED"\r
+        "MsmSig" = "8:_UNDEFINED"\r
+        }\r
+        "Entry"\r
+        {\r
+        "MsmKey" = "8:_E50F2FB950DD47D993DC8FB577266549"\r
+        "OwnerKey" = "8:_UNDEFINED"\r
+        "MsmSig" = "8:_UNDEFINED"\r
+        }\r
+        "Entry"\r
+        {\r
+        "MsmKey" = "8:_E7DD6A8D195B4752B0525628FF9586E4"\r
+        "OwnerKey" = "8:_UNDEFINED"\r
+        "MsmSig" = "8:_UNDEFINED"\r
+        }\r
+        "Entry"\r
+        {\r
+        "MsmKey" = "8:_E97571D3FBE048DABDC59B37762D800F"\r
+        "OwnerKey" = "8:_UNDEFINED"\r
+        "MsmSig" = "8:_UNDEFINED"\r
+        }\r
+        "Entry"\r
+        {\r
+        "MsmKey" = "8:_E9CA670571B5447682529CDB7BC3C100"\r
+        "OwnerKey" = "8:_UNDEFINED"\r
+        "MsmSig" = "8:_UNDEFINED"\r
+        }\r
+        "Entry"\r
+        {\r
+        "MsmKey" = "8:_EA282F32A10B4ED1A81AA6133B997C6A"\r
+        "OwnerKey" = "8:_UNDEFINED"\r
+        "MsmSig" = "8:_UNDEFINED"\r
+        }\r
+        "Entry"\r
+        {\r
+        "MsmKey" = "8:_EA9CE1B09EF1442BAA3C3F5AE7865ABF"\r
+        "OwnerKey" = "8:_UNDEFINED"\r
+        "MsmSig" = "8:_UNDEFINED"\r
+        }\r
+        "Entry"\r
+        {\r
+        "MsmKey" = "8:_EC7FE3265BDB4C52B5B87A8AC56AFDDD"\r
+        "OwnerKey" = "8:_UNDEFINED"\r
+        "MsmSig" = "8:_UNDEFINED"\r
+        }\r
+        "Entry"\r
+        {\r
+        "MsmKey" = "8:_F16FA7F9826E461E955A95B2EEABA975"\r
+        "OwnerKey" = "8:_UNDEFINED"\r
+        "MsmSig" = "8:_UNDEFINED"\r
+        }\r
+        "Entry"\r
+        {\r
+        "MsmKey" = "8:_F22F5380A6E14A43A15A452C7C6F6C07"\r
+        "OwnerKey" = "8:_UNDEFINED"\r
+        "MsmSig" = "8:_UNDEFINED"\r
+        }\r
+    }\r
+    "Configurations"\r
+    {\r
+        "Debug"\r
+        {\r
+        "DisplayName" = "8:Debug"\r
+        "IsDebugOnly" = "11:TRUE"\r
+        "IsReleaseOnly" = "11:FALSE"\r
+        "OutputFilename" = "8:ipptool-windows.msi"\r
+        "PackageFilesAs" = "3:2"\r
+        "PackageFileSize" = "3:-2147483648"\r
+        "CabType" = "3:1"\r
+        "Compression" = "3:3"\r
+        "SignOutput" = "11:FALSE"\r
+        "CertificateFile" = "8:"\r
+        "PrivateKeyFile" = "8:"\r
+        "TimeStampServer" = "8:"\r
+        "InstallerBootstrapper" = "3:2"\r
+            "BootstrapperCfg:{63ACBE69-63AA-4F98-B2B6-99F9E24495F2}"\r
+            {\r
+            "Enabled" = "11:TRUE"\r
+            "PromptEnabled" = "11:TRUE"\r
+            "PrerequisitesLocation" = "2:1"\r
+            "Url" = "8:"\r
+            "ComponentsUrl" = "8:"\r
+                "Items"\r
+                {\r
+                    "{EDC2488A-8267-493A-A98E-7D9C3B36CDF3}:Microsoft.Net.Framework.3.5.SP1"\r
+                    {\r
+                    "Name" = "8:.NET Framework 3.5 SP1"\r
+                    "ProductCode" = "8:Microsoft.Net.Framework.3.5.SP1"\r
+                    }\r
+                    "{EDC2488A-8267-493A-A98E-7D9C3B36CDF3}:Microsoft.Windows.Installer.3.1"\r
+                    {\r
+                    "Name" = "8:Windows Installer 3.1"\r
+                    "ProductCode" = "8:Microsoft.Windows.Installer.3.1"\r
+                    }\r
+                }\r
+            }\r
+        }\r
+        "Release"\r
+        {\r
+        "DisplayName" = "8:Release"\r
+        "IsDebugOnly" = "11:FALSE"\r
+        "IsReleaseOnly" = "11:TRUE"\r
+        "OutputFilename" = "8:ipptool-windows.msi"\r
+        "PackageFilesAs" = "3:2"\r
+        "PackageFileSize" = "3:-2147483648"\r
+        "CabType" = "3:1"\r
+        "Compression" = "3:3"\r
+        "SignOutput" = "11:FALSE"\r
+        "CertificateFile" = "8:"\r
+        "PrivateKeyFile" = "8:"\r
+        "TimeStampServer" = "8:"\r
+        "InstallerBootstrapper" = "3:2"\r
+            "BootstrapperCfg:{63ACBE69-63AA-4F98-B2B6-99F9E24495F2}"\r
+            {\r
+            "Enabled" = "11:TRUE"\r
+            "PromptEnabled" = "11:TRUE"\r
+            "PrerequisitesLocation" = "2:1"\r
+            "Url" = "8:"\r
+            "ComponentsUrl" = "8:"\r
+                "Items"\r
+                {\r
+                    "{EDC2488A-8267-493A-A98E-7D9C3B36CDF3}:Microsoft.Net.Framework.3.5.SP1"\r
+                    {\r
+                    "Name" = "8:.NET Framework 3.5 SP1"\r
+                    "ProductCode" = "8:Microsoft.Net.Framework.3.5.SP1"\r
+                    }\r
+                    "{EDC2488A-8267-493A-A98E-7D9C3B36CDF3}:Microsoft.Windows.Installer.3.1"\r
+                    {\r
+                    "Name" = "8:Windows Installer 3.1"\r
+                    "ProductCode" = "8:Microsoft.Windows.Installer.3.1"\r
+                    }\r
+                }\r
+            }\r
+        }\r
+    }\r
+    "Deployable"\r
+    {\r
+        "CustomAction"\r
+        {\r
+        }\r
+        "DefaultFeature"\r
+        {\r
+        "Name" = "8:DefaultFeature"\r
+        "Title" = "8:"\r
+        "Description" = "8:"\r
+        }\r
+        "ExternalPersistence"\r
+        {\r
+            "LaunchCondition"\r
+            {\r
+            }\r
+        }\r
+        "File"\r
+        {\r
+            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_009DC3ED78164048934ED35E89A0A1C5"\r
+            {\r
+            "SourcePath" = "8:..\\test\\document-a4.ps"\r
+            "TargetName" = "8:document-a4.ps"\r
+            "Tag" = "8:"\r
+            "Folder" = "8:_EB00D0298C7E441EBD0257AC04FB3560"\r
+            "Condition" = "8:"\r
+            "Transitive" = "11:FALSE"\r
+            "Vital" = "11:TRUE"\r
+            "ReadOnly" = "11:FALSE"\r
+            "Hidden" = "11:FALSE"\r
+            "System" = "11:FALSE"\r
+            "Permanent" = "11:FALSE"\r
+            "SharedLegacy" = "11:FALSE"\r
+            "PackageAs" = "3:1"\r
+            "Register" = "3:1"\r
+            "Exclude" = "11:FALSE"\r
+            "IsDependency" = "11:FALSE"\r
+            "IsolateTo" = "8:"\r
+            }\r
+            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_1A1324305D78463BBFC62269C56DCF0B"\r
+            {\r
+            "SourcePath" = "8:..\\doc\\help\\man-ipptoolfile.html"\r
+            "TargetName" = "8:man-ipptoolfile.html"\r
+            "Tag" = "8:"\r
+            "Folder" = "8:_FFAEDEA1D38D4088A03FDD6F17E2CA5D"\r
+            "Condition" = "8:"\r
+            "Transitive" = "11:FALSE"\r
+            "Vital" = "11:TRUE"\r
+            "ReadOnly" = "11:FALSE"\r
+            "Hidden" = "11:FALSE"\r
+            "System" = "11:FALSE"\r
+            "Permanent" = "11:FALSE"\r
+            "SharedLegacy" = "11:FALSE"\r
+            "PackageAs" = "3:1"\r
+            "Register" = "3:1"\r
+            "Exclude" = "11:FALSE"\r
+            "IsDependency" = "11:FALSE"\r
+            "IsolateTo" = "8:"\r
+            }\r
+            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_40C483299484486C9416B704F0EF4A6C"\r
+            {\r
+            "SourcePath" = "8:..\\test\\testfile.pdf"\r
+            "TargetName" = "8:testfile.pdf"\r
+            "Tag" = "8:"\r
+            "Folder" = "8:_EB00D0298C7E441EBD0257AC04FB3560"\r
+            "Condition" = "8:"\r
+            "Transitive" = "11:FALSE"\r
+            "Vital" = "11:TRUE"\r
+            "ReadOnly" = "11:FALSE"\r
+            "Hidden" = "11:FALSE"\r
+            "System" = "11:FALSE"\r
+            "Permanent" = "11:FALSE"\r
+            "SharedLegacy" = "11:FALSE"\r
+            "PackageAs" = "3:1"\r
+            "Register" = "3:1"\r
+            "Exclude" = "11:FALSE"\r
+            "IsDependency" = "11:FALSE"\r
+            "IsolateTo" = "8:"\r
+            }\r
+            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_41260853156249FDB39A8E386F935492"\r
+            {\r
+            "SourcePath" = "8:..\\test\\ipp-1.1.test"\r
+            "TargetName" = "8:ipp-1.1.test"\r
+            "Tag" = "8:"\r
+            "Folder" = "8:_EB00D0298C7E441EBD0257AC04FB3560"\r
+            "Condition" = "8:"\r
+            "Transitive" = "11:FALSE"\r
+            "Vital" = "11:TRUE"\r
+            "ReadOnly" = "11:FALSE"\r
+            "Hidden" = "11:FALSE"\r
+            "System" = "11:FALSE"\r
+            "Permanent" = "11:FALSE"\r
+            "SharedLegacy" = "11:FALSE"\r
+            "PackageAs" = "3:1"\r
+            "Register" = "3:1"\r
+            "Exclude" = "11:FALSE"\r
+            "IsDependency" = "11:FALSE"\r
+            "IsolateTo" = "8:"\r
+            }\r
+            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_425F2537D86148B9A4233AD27D426738"\r
+            {\r
+            "SourcePath" = "8:..\\test\\ipp-2.0.test"\r
+            "TargetName" = "8:ipp-2.0.test"\r
+            "Tag" = "8:"\r
+            "Folder" = "8:_EB00D0298C7E441EBD0257AC04FB3560"\r
+            "Condition" = "8:"\r
+            "Transitive" = "11:FALSE"\r
+            "Vital" = "11:TRUE"\r
+            "ReadOnly" = "11:FALSE"\r
+            "Hidden" = "11:FALSE"\r
+            "System" = "11:FALSE"\r
+            "Permanent" = "11:FALSE"\r
+            "SharedLegacy" = "11:FALSE"\r
+            "PackageAs" = "3:1"\r
+            "Register" = "3:1"\r
+            "Exclude" = "11:FALSE"\r
+            "IsDependency" = "11:FALSE"\r
+            "IsolateTo" = "8:"\r
+            }\r
+            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_65CBD149C9DA448FBACE2B02766A6537"\r
+            {\r
+            "SourcePath" = "8:..\\test\\testfile.ps"\r
+            "TargetName" = "8:testfile.ps"\r
+            "Tag" = "8:"\r
+            "Folder" = "8:_EB00D0298C7E441EBD0257AC04FB3560"\r
+            "Condition" = "8:"\r
+            "Transitive" = "11:FALSE"\r
+            "Vital" = "11:TRUE"\r
+            "ReadOnly" = "11:FALSE"\r
+            "Hidden" = "11:FALSE"\r
+            "System" = "11:FALSE"\r
+            "Permanent" = "11:FALSE"\r
+            "SharedLegacy" = "11:FALSE"\r
+            "PackageAs" = "3:1"\r
+            "Register" = "3:1"\r
+            "Exclude" = "11:FALSE"\r
+            "IsDependency" = "11:FALSE"\r
+            "IsolateTo" = "8:"\r
+            }\r
+            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_6F893B2A3B7048CBA39359FC368BCA27"\r
+            {\r
+            "SourcePath" = "8:..\\test\\onepage-letter.ps"\r
+            "TargetName" = "8:onepage-letter.ps"\r
+            "Tag" = "8:"\r
+            "Folder" = "8:_EB00D0298C7E441EBD0257AC04FB3560"\r
+            "Condition" = "8:"\r
+            "Transitive" = "11:FALSE"\r
+            "Vital" = "11:TRUE"\r
+            "ReadOnly" = "11:FALSE"\r
+            "Hidden" = "11:FALSE"\r
+            "System" = "11:FALSE"\r
+            "Permanent" = "11:FALSE"\r
+            "SharedLegacy" = "11:FALSE"\r
+            "PackageAs" = "3:1"\r
+            "Register" = "3:1"\r
+            "Exclude" = "11:FALSE"\r
+            "IsDependency" = "11:FALSE"\r
+            "IsolateTo" = "8:"\r
+            }\r
+            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_80DBA85C961E447CB92C95CE1F38C56B"\r
+            {\r
+            "SourcePath" = "8:..\\test\\ipp-2.2.test"\r
+            "TargetName" = "8:ipp-2.2.test"\r
+            "Tag" = "8:"\r
+            "Folder" = "8:_EB00D0298C7E441EBD0257AC04FB3560"\r
+            "Condition" = "8:"\r
+            "Transitive" = "11:FALSE"\r
+            "Vital" = "11:TRUE"\r
+            "ReadOnly" = "11:FALSE"\r
+            "Hidden" = "11:FALSE"\r
+            "System" = "11:FALSE"\r
+            "Permanent" = "11:FALSE"\r
+            "SharedLegacy" = "11:FALSE"\r
+            "PackageAs" = "3:1"\r
+            "Register" = "3:1"\r
+            "Exclude" = "11:FALSE"\r
+            "IsDependency" = "11:FALSE"\r
+            "IsolateTo" = "8:"\r
+            }\r
+            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_842C04D73EBC4F5DBC2FD58D5B98D5D1"\r
+            {\r
+            "SourcePath" = "8:..\\test\\document-a4.pdf"\r
+            "TargetName" = "8:document-a4.pdf"\r
+            "Tag" = "8:"\r
+            "Folder" = "8:_EB00D0298C7E441EBD0257AC04FB3560"\r
+            "Condition" = "8:"\r
+            "Transitive" = "11:FALSE"\r
+            "Vital" = "11:TRUE"\r
+            "ReadOnly" = "11:FALSE"\r
+            "Hidden" = "11:FALSE"\r
+            "System" = "11:FALSE"\r
+            "Permanent" = "11:FALSE"\r
+            "SharedLegacy" = "11:FALSE"\r
+            "PackageAs" = "3:1"\r
+            "Register" = "3:1"\r
+            "Exclude" = "11:FALSE"\r
+            "IsDependency" = "11:FALSE"\r
+            "IsolateTo" = "8:"\r
+            }\r
+            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_8AC6B9D7EF6B4C7A8C7B5AD85AA397C3"\r
+            {\r
+            "SourcePath" = "8:..\\test\\get-jobs.test"\r
+            "TargetName" = "8:get-jobs.test"\r
+            "Tag" = "8:"\r
+            "Folder" = "8:_EB00D0298C7E441EBD0257AC04FB3560"\r
+            "Condition" = "8:"\r
+            "Transitive" = "11:FALSE"\r
+            "Vital" = "11:TRUE"\r
+            "ReadOnly" = "11:FALSE"\r
+            "Hidden" = "11:FALSE"\r
+            "System" = "11:FALSE"\r
+            "Permanent" = "11:FALSE"\r
+            "SharedLegacy" = "11:FALSE"\r
+            "PackageAs" = "3:1"\r
+            "Register" = "3:1"\r
+            "Exclude" = "11:FALSE"\r
+            "IsDependency" = "11:FALSE"\r
+            "IsolateTo" = "8:"\r
+            }\r
+            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_8CC3562BCDED4676A672115D19D898B5"\r
+            {\r
+            "SourcePath" = "8:..\\test\\testfile.jpg"\r
+            "TargetName" = "8:testfile.jpg"\r
+            "Tag" = "8:"\r
+            "Folder" = "8:_EB00D0298C7E441EBD0257AC04FB3560"\r
+            "Condition" = "8:"\r
+            "Transitive" = "11:FALSE"\r
+            "Vital" = "11:TRUE"\r
+            "ReadOnly" = "11:FALSE"\r
+            "Hidden" = "11:FALSE"\r
+            "System" = "11:FALSE"\r
+            "Permanent" = "11:FALSE"\r
+            "SharedLegacy" = "11:FALSE"\r
+            "PackageAs" = "3:1"\r
+            "Register" = "3:1"\r
+            "Exclude" = "11:FALSE"\r
+            "IsDependency" = "11:FALSE"\r
+            "IsolateTo" = "8:"\r
+            }\r
+            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_9967519E7058965D4C7DEF47EB39CC50"\r
+            {\r
+            "SourcePath" = "8:CRYPT32.dll"\r
+            "TargetName" = "8:CRYPT32.dll"\r
+            "Tag" = "8:"\r
+            "Folder" = "8:_FFAEDEA1D38D4088A03FDD6F17E2CA5D"\r
+            "Condition" = "8:"\r
+            "Transitive" = "11:FALSE"\r
+            "Vital" = "11:TRUE"\r
+            "ReadOnly" = "11:FALSE"\r
+            "Hidden" = "11:FALSE"\r
+            "System" = "11:FALSE"\r
+            "Permanent" = "11:FALSE"\r
+            "SharedLegacy" = "11:FALSE"\r
+            "PackageAs" = "3:1"\r
+            "Register" = "3:1"\r
+            "Exclude" = "11:TRUE"\r
+            "IsDependency" = "11:TRUE"\r
+            "IsolateTo" = "8:"\r
+            }\r
+            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_9FBF78D7B89EEA843380D5F10E1954D7"\r
+            {\r
+            "SourcePath" = "8:Secur32.dll"\r
+            "TargetName" = "8:Secur32.dll"\r
+            "Tag" = "8:"\r
+            "Folder" = "8:_FFAEDEA1D38D4088A03FDD6F17E2CA5D"\r
+            "Condition" = "8:"\r
+            "Transitive" = "11:FALSE"\r
+            "Vital" = "11:TRUE"\r
+            "ReadOnly" = "11:FALSE"\r
+            "Hidden" = "11:FALSE"\r
+            "System" = "11:FALSE"\r
+            "Permanent" = "11:FALSE"\r
+            "SharedLegacy" = "11:FALSE"\r
+            "PackageAs" = "3:1"\r
+            "Register" = "3:1"\r
+            "Exclude" = "11:TRUE"\r
+            "IsDependency" = "11:TRUE"\r
+            "IsolateTo" = "8:"\r
+            }\r
+            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_AF057921D20E4520A3C6420F0729A744"\r
+            {\r
+            "SourcePath" = "8:..\\IPPTOOL.txt"\r
+            "TargetName" = "8:IPPTOOL.txt"\r
+            "Tag" = "8:"\r
+            "Folder" = "8:_FFAEDEA1D38D4088A03FDD6F17E2CA5D"\r
+            "Condition" = "8:"\r
+            "Transitive" = "11:FALSE"\r
+            "Vital" = "11:TRUE"\r
+            "ReadOnly" = "11:FALSE"\r
+            "Hidden" = "11:FALSE"\r
+            "System" = "11:FALSE"\r
+            "Permanent" = "11:FALSE"\r
+            "SharedLegacy" = "11:FALSE"\r
+            "PackageAs" = "3:1"\r
+            "Register" = "3:1"\r
+            "Exclude" = "11:FALSE"\r
+            "IsDependency" = "11:FALSE"\r
+            "IsolateTo" = "8:"\r
+            }\r
+            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_B9E79062FEF64745915546DDD5BF8D85"\r
+            {\r
+            "SourcePath" = "8:..\\CHANGES-IPPTOOL.txt"\r
+            "TargetName" = "8:CHANGES-IPPTOOL.txt"\r
+            "Tag" = "8:"\r
+            "Folder" = "8:_FFAEDEA1D38D4088A03FDD6F17E2CA5D"\r
+            "Condition" = "8:"\r
+            "Transitive" = "11:FALSE"\r
+            "Vital" = "11:TRUE"\r
+            "ReadOnly" = "11:FALSE"\r
+            "Hidden" = "11:FALSE"\r
+            "System" = "11:FALSE"\r
+            "Permanent" = "11:FALSE"\r
+            "SharedLegacy" = "11:FALSE"\r
+            "PackageAs" = "3:1"\r
+            "Register" = "3:1"\r
+            "Exclude" = "11:FALSE"\r
+            "IsDependency" = "11:FALSE"\r
+            "IsolateTo" = "8:"\r
+            }\r
+            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_C430646D6E7C4CBDA84F951AE95EB76F"\r
+            {\r
+            "SourcePath" = "8:..\\test\\color.jpg"\r
+            "TargetName" = "8:color.jpg"\r
+            "Tag" = "8:"\r
+            "Folder" = "8:_EB00D0298C7E441EBD0257AC04FB3560"\r
+            "Condition" = "8:"\r
+            "Transitive" = "11:FALSE"\r
+            "Vital" = "11:TRUE"\r
+            "ReadOnly" = "11:FALSE"\r
+            "Hidden" = "11:FALSE"\r
+            "System" = "11:FALSE"\r
+            "Permanent" = "11:FALSE"\r
+            "SharedLegacy" = "11:FALSE"\r
+            "PackageAs" = "3:1"\r
+            "Register" = "3:1"\r
+            "Exclude" = "11:FALSE"\r
+            "IsDependency" = "11:FALSE"\r
+            "IsolateTo" = "8:"\r
+            }\r
+            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_D4BEA026ABFB46DD960AD8EFCAE45E31"\r
+            {\r
+            "SourcePath" = "8:..\\test\\onepage-letter.pdf"\r
+            "TargetName" = "8:onepage-letter.pdf"\r
+            "Tag" = "8:"\r
+            "Folder" = "8:_EB00D0298C7E441EBD0257AC04FB3560"\r
+            "Condition" = "8:"\r
+            "Transitive" = "11:FALSE"\r
+            "Vital" = "11:TRUE"\r
+            "ReadOnly" = "11:FALSE"\r
+            "Hidden" = "11:FALSE"\r
+            "System" = "11:FALSE"\r
+            "Permanent" = "11:FALSE"\r
+            "SharedLegacy" = "11:FALSE"\r
+            "PackageAs" = "3:1"\r
+            "Register" = "3:1"\r
+            "Exclude" = "11:FALSE"\r
+            "IsDependency" = "11:FALSE"\r
+            "IsolateTo" = "8:"\r
+            }\r
+            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_D5CD9D9AB1644688A1D54B1589BDF724"\r
+            {\r
+            "SourcePath" = "8:..\\doc\\help\\man-ipptool.html"\r
+            "TargetName" = "8:man-ipptool.html"\r
+            "Tag" = "8:"\r
+            "Folder" = "8:_FFAEDEA1D38D4088A03FDD6F17E2CA5D"\r
+            "Condition" = "8:"\r
+            "Transitive" = "11:FALSE"\r
+            "Vital" = "11:TRUE"\r
+            "ReadOnly" = "11:FALSE"\r
+            "Hidden" = "11:FALSE"\r
+            "System" = "11:FALSE"\r
+            "Permanent" = "11:FALSE"\r
+            "SharedLegacy" = "11:FALSE"\r
+            "PackageAs" = "3:1"\r
+            "Register" = "3:1"\r
+            "Exclude" = "11:FALSE"\r
+            "IsDependency" = "11:FALSE"\r
+            "IsolateTo" = "8:"\r
+            }\r
+            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_E30823E684384F4DB7385B14F714AD95"\r
+            {\r
+            "SourcePath" = "8:..\\test\\ipp-2.1.test"\r
+            "TargetName" = "8:ipp-2.1.test"\r
+            "Tag" = "8:"\r
+            "Folder" = "8:_EB00D0298C7E441EBD0257AC04FB3560"\r
+            "Condition" = "8:"\r
+            "Transitive" = "11:FALSE"\r
+            "Vital" = "11:TRUE"\r
+            "ReadOnly" = "11:FALSE"\r
+            "Hidden" = "11:FALSE"\r
+            "System" = "11:FALSE"\r
+            "Permanent" = "11:FALSE"\r
+            "SharedLegacy" = "11:FALSE"\r
+            "PackageAs" = "3:1"\r
+            "Register" = "3:1"\r
+            "Exclude" = "11:FALSE"\r
+            "IsDependency" = "11:FALSE"\r
+            "IsolateTo" = "8:"\r
+            }\r
+            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_E3C6C5A7FDD94965B68960844461D5EA"\r
+            {\r
+            "SourcePath" = "8:..\\LICENSE.txt"\r
+            "TargetName" = "8:LICENSE.txt"\r
+            "Tag" = "8:"\r
+            "Folder" = "8:_FFAEDEA1D38D4088A03FDD6F17E2CA5D"\r
+            "Condition" = "8:"\r
+            "Transitive" = "11:FALSE"\r
+            "Vital" = "11:TRUE"\r
+            "ReadOnly" = "11:FALSE"\r
+            "Hidden" = "11:FALSE"\r
+            "System" = "11:FALSE"\r
+            "Permanent" = "11:FALSE"\r
+            "SharedLegacy" = "11:FALSE"\r
+            "PackageAs" = "3:1"\r
+            "Register" = "3:1"\r
+            "Exclude" = "11:FALSE"\r
+            "IsDependency" = "11:FALSE"\r
+            "IsolateTo" = "8:"\r
+            }\r
+            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_E4C0F67094B94E05AB69787080727089"\r
+            {\r
+            "SourcePath" = "8:..\\test\\create-printer-subscription.test"\r
+            "TargetName" = "8:create-printer-subscription.test"\r
+            "Tag" = "8:"\r
+            "Folder" = "8:_EB00D0298C7E441EBD0257AC04FB3560"\r
+            "Condition" = "8:"\r
+            "Transitive" = "11:FALSE"\r
+            "Vital" = "11:TRUE"\r
+            "ReadOnly" = "11:FALSE"\r
+            "Hidden" = "11:FALSE"\r
+            "System" = "11:FALSE"\r
+            "Permanent" = "11:FALSE"\r
+            "SharedLegacy" = "11:FALSE"\r
+            "PackageAs" = "3:1"\r
+            "Register" = "3:1"\r
+            "Exclude" = "11:FALSE"\r
+            "IsDependency" = "11:FALSE"\r
+            "IsolateTo" = "8:"\r
+            }\r
+            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_E50F2FB950DD47D993DC8FB577266549"\r
+            {\r
+            "SourcePath" = "8:..\\test\\document-letter.ps"\r
+            "TargetName" = "8:document-letter.ps"\r
+            "Tag" = "8:"\r
+            "Folder" = "8:_EB00D0298C7E441EBD0257AC04FB3560"\r
+            "Condition" = "8:"\r
+            "Transitive" = "11:FALSE"\r
+            "Vital" = "11:TRUE"\r
+            "ReadOnly" = "11:FALSE"\r
+            "Hidden" = "11:FALSE"\r
+            "System" = "11:FALSE"\r
+            "Permanent" = "11:FALSE"\r
+            "SharedLegacy" = "11:FALSE"\r
+            "PackageAs" = "3:1"\r
+            "Register" = "3:1"\r
+            "Exclude" = "11:FALSE"\r
+            "IsDependency" = "11:FALSE"\r
+            "IsolateTo" = "8:"\r
+            }\r
+            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_E7DD6A8D195B4752B0525628FF9586E4"\r
+            {\r
+            "SourcePath" = "8:..\\test\\onepage-a4.ps"\r
+            "TargetName" = "8:onepage-a4.ps"\r
+            "Tag" = "8:"\r
+            "Folder" = "8:_EB00D0298C7E441EBD0257AC04FB3560"\r
+            "Condition" = "8:"\r
+            "Transitive" = "11:FALSE"\r
+            "Vital" = "11:TRUE"\r
+            "ReadOnly" = "11:FALSE"\r
+            "Hidden" = "11:FALSE"\r
+            "System" = "11:FALSE"\r
+            "Permanent" = "11:FALSE"\r
+            "SharedLegacy" = "11:FALSE"\r
+            "PackageAs" = "3:1"\r
+            "Register" = "3:1"\r
+            "Exclude" = "11:FALSE"\r
+            "IsDependency" = "11:FALSE"\r
+            "IsolateTo" = "8:"\r
+            }\r
+            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_E9CA670571B5447682529CDB7BC3C100"\r
+            {\r
+            "SourcePath" = "8:..\\test\\gray.jpg"\r
+            "TargetName" = "8:gray.jpg"\r
+            "Tag" = "8:"\r
+            "Folder" = "8:_EB00D0298C7E441EBD0257AC04FB3560"\r
+            "Condition" = "8:"\r
+            "Transitive" = "11:FALSE"\r
+            "Vital" = "11:TRUE"\r
+            "ReadOnly" = "11:FALSE"\r
+            "Hidden" = "11:FALSE"\r
+            "System" = "11:FALSE"\r
+            "Permanent" = "11:FALSE"\r
+            "SharedLegacy" = "11:FALSE"\r
+            "PackageAs" = "3:1"\r
+            "Register" = "3:1"\r
+            "Exclude" = "11:FALSE"\r
+            "IsDependency" = "11:FALSE"\r
+            "IsolateTo" = "8:"\r
+            }\r
+            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_EA9CE1B09EF1442BAA3C3F5AE7865ABF"\r
+            {\r
+            "SourcePath" = "8:..\\test\\testfile.txt"\r
+            "TargetName" = "8:testfile.txt"\r
+            "Tag" = "8:"\r
+            "Folder" = "8:_EB00D0298C7E441EBD0257AC04FB3560"\r
+            "Condition" = "8:"\r
+            "Transitive" = "11:FALSE"\r
+            "Vital" = "11:TRUE"\r
+            "ReadOnly" = "11:FALSE"\r
+            "Hidden" = "11:FALSE"\r
+            "System" = "11:FALSE"\r
+            "Permanent" = "11:FALSE"\r
+            "SharedLegacy" = "11:FALSE"\r
+            "PackageAs" = "3:1"\r
+            "Register" = "3:1"\r
+            "Exclude" = "11:FALSE"\r
+            "IsDependency" = "11:FALSE"\r
+            "IsolateTo" = "8:"\r
+            }\r
+            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_EC7FE3265BDB4C52B5B87A8AC56AFDDD"\r
+            {\r
+            "SourcePath" = "8:..\\test\\get-completed-jobs.test"\r
+            "TargetName" = "8:get-completed-jobs.test"\r
+            "Tag" = "8:"\r
+            "Folder" = "8:_EB00D0298C7E441EBD0257AC04FB3560"\r
+            "Condition" = "8:"\r
+            "Transitive" = "11:FALSE"\r
+            "Vital" = "11:TRUE"\r
+            "ReadOnly" = "11:FALSE"\r
+            "Hidden" = "11:FALSE"\r
+            "System" = "11:FALSE"\r
+            "Permanent" = "11:FALSE"\r
+            "SharedLegacy" = "11:FALSE"\r
+            "PackageAs" = "3:1"\r
+            "Register" = "3:1"\r
+            "Exclude" = "11:FALSE"\r
+            "IsDependency" = "11:FALSE"\r
+            "IsolateTo" = "8:"\r
+            }\r
+            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_F16FA7F9826E461E955A95B2EEABA975"\r
+            {\r
+            "SourcePath" = "8:..\\test\\onepage-a4.pdf"\r
+            "TargetName" = "8:onepage-a4.pdf"\r
+            "Tag" = "8:"\r
+            "Folder" = "8:_EB00D0298C7E441EBD0257AC04FB3560"\r
+            "Condition" = "8:"\r
+            "Transitive" = "11:FALSE"\r
+            "Vital" = "11:TRUE"\r
+            "ReadOnly" = "11:FALSE"\r
+            "Hidden" = "11:FALSE"\r
+            "System" = "11:FALSE"\r
+            "Permanent" = "11:FALSE"\r
+            "SharedLegacy" = "11:FALSE"\r
+            "PackageAs" = "3:1"\r
+            "Register" = "3:1"\r
+            "Exclude" = "11:FALSE"\r
+            "IsDependency" = "11:FALSE"\r
+            "IsolateTo" = "8:"\r
+            }\r
+            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_F22F5380A6E14A43A15A452C7C6F6C07"\r
+            {\r
+            "SourcePath" = "8:..\\test\\document-letter.pdf"\r
+            "TargetName" = "8:document-letter.pdf"\r
+            "Tag" = "8:"\r
+            "Folder" = "8:_EB00D0298C7E441EBD0257AC04FB3560"\r
+            "Condition" = "8:"\r
+            "Transitive" = "11:FALSE"\r
+            "Vital" = "11:TRUE"\r
+            "ReadOnly" = "11:FALSE"\r
+            "Hidden" = "11:FALSE"\r
+            "System" = "11:FALSE"\r
+            "Permanent" = "11:FALSE"\r
+            "SharedLegacy" = "11:FALSE"\r
+            "PackageAs" = "3:1"\r
+            "Register" = "3:1"\r
+            "Exclude" = "11:FALSE"\r
+            "IsDependency" = "11:FALSE"\r
+            "IsolateTo" = "8:"\r
+            }\r
+        }\r
+        "FileType"\r
+        {\r
+        }\r
+        "Folder"\r
+        {\r
+            "{1525181F-901A-416C-8A58-119130FE478E}:_BEC0EAE20C954C78B294B83E6696156E"\r
+            {\r
+            "Name" = "8:#1919"\r
+            "AlwaysCreate" = "11:FALSE"\r
+            "Condition" = "8:"\r
+            "Transitive" = "11:FALSE"\r
+            "Property" = "8:ProgramMenuFolder"\r
+                "Folders"\r
+                {\r
+                }\r
+            }\r
+            "{1525181F-901A-416C-8A58-119130FE478E}:_D02CDADE99F344CF92CA1A8D0278861F"\r
+            {\r
+            "Name" = "8:#1916"\r
+            "AlwaysCreate" = "11:FALSE"\r
+            "Condition" = "8:"\r
+            "Transitive" = "11:FALSE"\r
+            "Property" = "8:DesktopFolder"\r
+                "Folders"\r
+                {\r
+                }\r
+            }\r
+            "{3C67513D-01DD-4637-8A68-80971EB9504F}:_FFAEDEA1D38D4088A03FDD6F17E2CA5D"\r
+            {\r
+            "DefaultLocation" = "8:[ProgramFilesFolder]\\ipptool"\r
+            "Name" = "8:#1925"\r
+            "AlwaysCreate" = "11:FALSE"\r
+            "Condition" = "8:"\r
+            "Transitive" = "11:FALSE"\r
+            "Property" = "8:TARGETDIR"\r
+                "Folders"\r
+                {\r
+                    "{9EF0B969-E518-4E46-987F-47570745A589}:_EB00D0298C7E441EBD0257AC04FB3560"\r
+                    {\r
+                    "Name" = "8:ipptool"\r
+                    "AlwaysCreate" = "11:FALSE"\r
+                    "Condition" = "8:"\r
+                    "Transitive" = "11:FALSE"\r
+                    "Property" = "8:_6F223FB51798428A9F2D64A5A7F2B49C"\r
+                        "Folders"\r
+                        {\r
+                        }\r
+                    }\r
+                }\r
+            }\r
+        }\r
+        "LaunchCondition"\r
+        {\r
+        }\r
+        "Locator"\r
+        {\r
+        }\r
+        "MsiBootstrapper"\r
+        {\r
+        "LangId" = "3:1033"\r
+        "RequiresElevation" = "11:FALSE"\r
+        }\r
+        "Product"\r
+        {\r
+        "Name" = "8:Microsoft Visual Studio"\r
+        "ProductName" = "8:ipptool for Windows"\r
+        "ProductCode" = "8:{491DCF72-4D28-4670-B775-1639941F22FD}"\r
+        "PackageCode" = "8:{6EDF8426-DBF4-485B-AFDA-2F6A0BAC642F}"\r
+        "UpgradeCode" = "8:{BAB6EBBB-515D-4155-9FEF-D98DA76814CA}"\r
+        "RestartWWWService" = "11:FALSE"\r
+        "RemovePreviousVersions" = "11:TRUE"\r
+        "DetectNewerInstalledVersion" = "11:TRUE"\r
+        "InstallAllUsers" = "11:TRUE"\r
+        "ProductVersion" = "8:11.10.0700"\r
+        "Manufacturer" = "8:Apple Inc."\r
+        "ARPHELPTELEPHONE" = "8:"\r
+        "ARPHELPLINK" = "8:http://www.cups.org/str.php"\r
+        "Title" = "8:ipptool"\r
+        "Subject" = "8:"\r
+        "ARPCONTACT" = "8:Apple Inc."\r
+        "Keywords" = "8:IPP, Internet Printing Protocol"\r
+        "ARPCOMMENTS" = "8:ipptool for Windows"\r
+        "ARPURLINFOABOUT" = "8:http://www.cups.org/"\r
+        "ARPPRODUCTICON" = "8:"\r
+        "ARPIconIndex" = "3:0"\r
+        "SearchPath" = "8:"\r
+        "UseSystemSearchPath" = "11:TRUE"\r
+        "TargetPlatform" = "3:0"\r
+        "PreBuildEvent" = "8:"\r
+        "PostBuildEvent" = "8:"\r
+        "RunPostBuildEvent" = "3:0"\r
+        }\r
+        "Registry"\r
+        {\r
+            "HKLM"\r
+            {\r
+                "Keys"\r
+                {\r
+                    "{60EA8692-D2D5-43EB-80DC-7906BF13D6EF}:_BC4E66686BCA4F9A8B24B6CF2728DACD"\r
+                    {\r
+                    "Name" = "8:Software"\r
+                    "Condition" = "8:"\r
+                    "AlwaysCreate" = "11:FALSE"\r
+                    "DeleteAtUninstall" = "11:FALSE"\r
+                    "Transitive" = "11:FALSE"\r
+                        "Keys"\r
+                        {\r
+                            "{60EA8692-D2D5-43EB-80DC-7906BF13D6EF}:_F9AB9B310C7545D993D690F529048AA2"\r
+                            {\r
+                            "Name" = "8:cups.org"\r
+                            "Condition" = "8:"\r
+                            "AlwaysCreate" = "11:FALSE"\r
+                            "DeleteAtUninstall" = "11:FALSE"\r
+                            "Transitive" = "11:FALSE"\r
+                                "Keys"\r
+                                {\r
+                                }\r
+                                "Values"\r
+                                {\r
+                                    "{ADCFDA98-8FDD-45E4-90BC-E3D20B029870}:_4E5BAC705A1D44E78C90C6D2A4A7BE20"\r
+                                    {\r
+                                    "Name" = "8:installdir"\r
+                                    "Condition" = "8:"\r
+                                    "Transitive" = "11:FALSE"\r
+                                    "ValueTypes" = "3:2"\r
+                                    "Value" = "8:[TARGETDIR]"\r
+                                    }\r
+                                }\r
+                            }\r
+                        }\r
+                        "Values"\r
+                        {\r
+                        }\r
+                    }\r
+                }\r
+            }\r
+            "HKCU"\r
+            {\r
+                "Keys"\r
+                {\r
+                    "{60EA8692-D2D5-43EB-80DC-7906BF13D6EF}:_A4C9879F42874B6B92960A55F2D98922"\r
+                    {\r
+                    "Name" = "8:Software"\r
+                    "Condition" = "8:"\r
+                    "AlwaysCreate" = "11:FALSE"\r
+                    "DeleteAtUninstall" = "11:FALSE"\r
+                    "Transitive" = "11:FALSE"\r
+                        "Keys"\r
+                        {\r
+                            "{60EA8692-D2D5-43EB-80DC-7906BF13D6EF}:_1ACB03C307FB4B85BB27C9913FB58B09"\r
+                            {\r
+                            "Name" = "8:[Manufacturer]"\r
+                            "Condition" = "8:"\r
+                            "AlwaysCreate" = "11:FALSE"\r
+                            "DeleteAtUninstall" = "11:FALSE"\r
+                            "Transitive" = "11:FALSE"\r
+                                "Keys"\r
+                                {\r
+                                }\r
+                                "Values"\r
+                                {\r
+                                }\r
+                            }\r
+                        }\r
+                        "Values"\r
+                        {\r
+                        }\r
+                    }\r
+                }\r
+            }\r
+            "HKCR"\r
+            {\r
+                "Keys"\r
+                {\r
+                }\r
+            }\r
+            "HKU"\r
+            {\r
+                "Keys"\r
+                {\r
+                }\r
+            }\r
+            "HKPU"\r
+            {\r
+                "Keys"\r
+                {\r
+                }\r
+            }\r
+        }\r
+        "Sequences"\r
+        {\r
+        }\r
+        "Shortcut"\r
+        {\r
+        }\r
+        "UserInterface"\r
+        {\r
+            "{2479F3F5-0309-486D-8047-8187E2CE5BA0}:_045DF90B1FF941A9BA7A742CFC0A6C00"\r
+            {\r
+            "UseDynamicProperties" = "11:FALSE"\r
+            "IsDependency" = "11:FALSE"\r
+            "SourcePath" = "8:<VsdDialogDir>\\VsdUserInterface.wim"\r
+            }\r
+            "{DF760B10-853B-4699-99F2-AFF7185B4A62}:_345BD86390E841A98B74ED3E07945F8C"\r
+            {\r
+            "Name" = "8:#1900"\r
+            "Sequence" = "3:2"\r
+            "Attributes" = "3:1"\r
+                "Dialogs"\r
+                {\r
+                    "{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_067C143A8731427180B1568AF8C07375"\r
+                    {\r
+                    "Sequence" = "3:200"\r
+                    "DisplayName" = "8:Installation Folder"\r
+                    "UseDynamicProperties" = "11:TRUE"\r
+                    "IsDependency" = "11:FALSE"\r
+                    "SourcePath" = "8:<VsdDialogDir>\\VsdAdminFolderDlg.wid"\r
+                        "Properties"\r
+                        {\r
+                            "BannerBitmap"\r
+                            {\r
+                            "Name" = "8:BannerBitmap"\r
+                            "DisplayName" = "8:#1001"\r
+                            "Description" = "8:#1101"\r
+                            "Type" = "3:8"\r
+                            "ContextData" = "8:Bitmap"\r
+                            "Attributes" = "3:4"\r
+                            "Setting" = "3:1"\r
+                            "UsePlugInResources" = "11:TRUE"\r
+                            }\r
+                        }\r
+                    }\r
+                    "{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_A2F2CC6EB9D7453599E7598D4D0629A5"\r
+                    {\r
+                    "Sequence" = "3:300"\r
+                    "DisplayName" = "8:Confirm Installation"\r
+                    "UseDynamicProperties" = "11:TRUE"\r
+                    "IsDependency" = "11:FALSE"\r
+                    "SourcePath" = "8:<VsdDialogDir>\\VsdAdminConfirmDlg.wid"\r
+                        "Properties"\r
+                        {\r
+                            "BannerBitmap"\r
+                            {\r
+                            "Name" = "8:BannerBitmap"\r
+                            "DisplayName" = "8:#1001"\r
+                            "Description" = "8:#1101"\r
+                            "Type" = "3:8"\r
+                            "ContextData" = "8:Bitmap"\r
+                            "Attributes" = "3:4"\r
+                            "Setting" = "3:1"\r
+                            "UsePlugInResources" = "11:TRUE"\r
+                            }\r
+                        }\r
+                    }\r
+                    "{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_C2B41369B7334F419318792EBA031412"\r
+                    {\r
+                    "Sequence" = "3:100"\r
+                    "DisplayName" = "8:Welcome"\r
+                    "UseDynamicProperties" = "11:TRUE"\r
+                    "IsDependency" = "11:FALSE"\r
+                    "SourcePath" = "8:<VsdDialogDir>\\VsdAdminWelcomeDlg.wid"\r
+                        "Properties"\r
+                        {\r
+                            "BannerBitmap"\r
+                            {\r
+                            "Name" = "8:BannerBitmap"\r
+                            "DisplayName" = "8:#1001"\r
+                            "Description" = "8:#1101"\r
+                            "Type" = "3:8"\r
+                            "ContextData" = "8:Bitmap"\r
+                            "Attributes" = "3:4"\r
+                            "Setting" = "3:1"\r
+                            "UsePlugInResources" = "11:TRUE"\r
+                            }\r
+                            "CopyrightWarning"\r
+                            {\r
+                            "Name" = "8:CopyrightWarning"\r
+                            "DisplayName" = "8:#1002"\r
+                            "Description" = "8:#1102"\r
+                            "Type" = "3:3"\r
+                            "ContextData" = "8:"\r
+                            "Attributes" = "3:0"\r
+                            "Setting" = "3:2"\r
+                            "Value" = "8:This computer program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2."\r
+                            "DefaultValue" = "8:#1202"\r
+                            "UsePlugInResources" = "11:TRUE"\r
+                            }\r
+                            "Welcome"\r
+                            {\r
+                            "Name" = "8:Welcome"\r
+                            "DisplayName" = "8:#1003"\r
+                            "Description" = "8:#1103"\r
+                            "Type" = "3:3"\r
+                            "ContextData" = "8:"\r
+                            "Attributes" = "3:0"\r
+                            "Setting" = "3:1"\r
+                            "Value" = "8:#1203"\r
+                            "DefaultValue" = "8:#1203"\r
+                            "UsePlugInResources" = "11:TRUE"\r
+                            }\r
+                        }\r
+                    }\r
+                }\r
+            }\r
+            "{DF760B10-853B-4699-99F2-AFF7185B4A62}:_6B654A06090344BA9AA443E0D0296737"\r
+            {\r
+            "Name" = "8:#1902"\r
+            "Sequence" = "3:1"\r
+            "Attributes" = "3:3"\r
+                "Dialogs"\r
+                {\r
+                    "{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_FB4E7BBC3DA242309FFB58F9A6194A93"\r
+                    {\r
+                    "Sequence" = "3:100"\r
+                    "DisplayName" = "8:Finished"\r
+                    "UseDynamicProperties" = "11:TRUE"\r
+                    "IsDependency" = "11:FALSE"\r
+                    "SourcePath" = "8:<VsdDialogDir>\\VsdFinishedDlg.wid"\r
+                        "Properties"\r
+                        {\r
+                            "BannerBitmap"\r
+                            {\r
+                            "Name" = "8:BannerBitmap"\r
+                            "DisplayName" = "8:#1001"\r
+                            "Description" = "8:#1101"\r
+                            "Type" = "3:8"\r
+                            "ContextData" = "8:Bitmap"\r
+                            "Attributes" = "3:4"\r
+                            "Setting" = "3:1"\r
+                            "UsePlugInResources" = "11:TRUE"\r
+                            }\r
+                            "UpdateText"\r
+                            {\r
+                            "Name" = "8:UpdateText"\r
+                            "DisplayName" = "8:#1058"\r
+                            "Description" = "8:#1158"\r
+                            "Type" = "3:15"\r
+                            "ContextData" = "8:"\r
+                            "Attributes" = "3:0"\r
+                            "Setting" = "3:1"\r
+                            "Value" = "8:#1258"\r
+                            "DefaultValue" = "8:#1258"\r
+                            "UsePlugInResources" = "11:TRUE"\r
+                            }\r
+                        }\r
+                    }\r
+                }\r
+            }\r
+            "{DF760B10-853B-4699-99F2-AFF7185B4A62}:_712819C7C4F042ABB708949BD4426628"\r
+            {\r
+            "Name" = "8:#1900"\r
+            "Sequence" = "3:1"\r
+            "Attributes" = "3:1"\r
+                "Dialogs"\r
+                {\r
+                    "{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_2F49D4FACB954AF2B786D2AD9206D053"\r
+                    {\r
+                    "Sequence" = "3:100"\r
+                    "DisplayName" = "8:Welcome"\r
+                    "UseDynamicProperties" = "11:TRUE"\r
+                    "IsDependency" = "11:FALSE"\r
+                    "SourcePath" = "8:<VsdDialogDir>\\VsdWelcomeDlg.wid"\r
+                        "Properties"\r
+                        {\r
+                            "BannerBitmap"\r
+                            {\r
+                            "Name" = "8:BannerBitmap"\r
+                            "DisplayName" = "8:#1001"\r
+                            "Description" = "8:#1101"\r
+                            "Type" = "3:8"\r
+                            "ContextData" = "8:Bitmap"\r
+                            "Attributes" = "3:4"\r
+                            "Setting" = "3:1"\r
+                            "UsePlugInResources" = "11:TRUE"\r
+                            }\r
+                            "CopyrightWarning"\r
+                            {\r
+                            "Name" = "8:CopyrightWarning"\r
+                            "DisplayName" = "8:#1002"\r
+                            "Description" = "8:#1102"\r
+                            "Type" = "3:3"\r
+                            "ContextData" = "8:"\r
+                            "Attributes" = "3:0"\r
+                            "Setting" = "3:2"\r
+                            "Value" = "8:This computer program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2."\r
+                            "DefaultValue" = "8:#1202"\r
+                            "UsePlugInResources" = "11:TRUE"\r
+                            }\r
+                            "Welcome"\r
+                            {\r
+                            "Name" = "8:Welcome"\r
+                            "DisplayName" = "8:#1003"\r
+                            "Description" = "8:#1103"\r
+                            "Type" = "3:3"\r
+                            "ContextData" = "8:"\r
+                            "Attributes" = "3:0"\r
+                            "Setting" = "3:1"\r
+                            "Value" = "8:#1203"\r
+                            "DefaultValue" = "8:#1203"\r
+                            "UsePlugInResources" = "11:TRUE"\r
+                            }\r
+                        }\r
+                    }\r
+                    "{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_770E25BC453A464EA8CD51381FDDDD9F"\r
+                    {\r
+                    "Sequence" = "3:300"\r
+                    "DisplayName" = "8:Confirm Installation"\r
+                    "UseDynamicProperties" = "11:TRUE"\r
+                    "IsDependency" = "11:FALSE"\r
+                    "SourcePath" = "8:<VsdDialogDir>\\VsdConfirmDlg.wid"\r
+                        "Properties"\r
+                        {\r
+                            "BannerBitmap"\r
+                            {\r
+                            "Name" = "8:BannerBitmap"\r
+                            "DisplayName" = "8:#1001"\r
+                            "Description" = "8:#1101"\r
+                            "Type" = "3:8"\r
+                            "ContextData" = "8:Bitmap"\r
+                            "Attributes" = "3:4"\r
+                            "Setting" = "3:1"\r
+                            "UsePlugInResources" = "11:TRUE"\r
+                            }\r
+                        }\r
+                    }\r
+                    "{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_9534A64B629F4F868D6D7A384C76DCB2"\r
+                    {\r
+                    "Sequence" = "3:200"\r
+                    "DisplayName" = "8:Installation Folder"\r
+                    "UseDynamicProperties" = "11:TRUE"\r
+                    "IsDependency" = "11:FALSE"\r
+                    "SourcePath" = "8:<VsdDialogDir>\\VsdFolderDlg.wid"\r
+                        "Properties"\r
+                        {\r
+                            "BannerBitmap"\r
+                            {\r
+                            "Name" = "8:BannerBitmap"\r
+                            "DisplayName" = "8:#1001"\r
+                            "Description" = "8:#1101"\r
+                            "Type" = "3:8"\r
+                            "ContextData" = "8:Bitmap"\r
+                            "Attributes" = "3:4"\r
+                            "Setting" = "3:1"\r
+                            "UsePlugInResources" = "11:TRUE"\r
+                            }\r
+                            "InstallAllUsersVisible"\r
+                            {\r
+                            "Name" = "8:InstallAllUsersVisible"\r
+                            "DisplayName" = "8:#1059"\r
+                            "Description" = "8:#1159"\r
+                            "Type" = "3:5"\r
+                            "ContextData" = "8:1;True=1;False=0"\r
+                            "Attributes" = "3:0"\r
+                            "Setting" = "3:0"\r
+                            "Value" = "3:1"\r
+                            "DefaultValue" = "3:1"\r
+                            "UsePlugInResources" = "11:TRUE"\r
+                            }\r
+                        }\r
+                    }\r
+                }\r
+            }\r
+            "{DF760B10-853B-4699-99F2-AFF7185B4A62}:_770CCEFF81BD46A182A6E816A41A0E81"\r
+            {\r
+            "Name" = "8:#1901"\r
+            "Sequence" = "3:2"\r
+            "Attributes" = "3:2"\r
+                "Dialogs"\r
+                {\r
+                    "{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_75E0C1FD245D493DA0D7E3E0BC0C365F"\r
+                    {\r
+                    "Sequence" = "3:100"\r
+                    "DisplayName" = "8:Progress"\r
+                    "UseDynamicProperties" = "11:TRUE"\r
+                    "IsDependency" = "11:FALSE"\r
+                    "SourcePath" = "8:<VsdDialogDir>\\VsdAdminProgressDlg.wid"\r
+                        "Properties"\r
+                        {\r
+                            "BannerBitmap"\r
+                            {\r
+                            "Name" = "8:BannerBitmap"\r
+                            "DisplayName" = "8:#1001"\r
+                            "Description" = "8:#1101"\r
+                            "Type" = "3:8"\r
+                            "ContextData" = "8:Bitmap"\r
+                            "Attributes" = "3:4"\r
+                            "Setting" = "3:1"\r
+                            "UsePlugInResources" = "11:TRUE"\r
+                            }\r
+                            "ShowProgress"\r
+                            {\r
+                            "Name" = "8:ShowProgress"\r
+                            "DisplayName" = "8:#1009"\r
+                            "Description" = "8:#1109"\r
+                            "Type" = "3:5"\r
+                            "ContextData" = "8:1;True=1;False=0"\r
+                            "Attributes" = "3:0"\r
+                            "Setting" = "3:0"\r
+                            "Value" = "3:1"\r
+                            "DefaultValue" = "3:1"\r
+                            "UsePlugInResources" = "11:TRUE"\r
+                            }\r
+                        }\r
+                    }\r
+                }\r
+            }\r
+            "{2479F3F5-0309-486D-8047-8187E2CE5BA0}:_933B15E9A383418F8ADF3B13F68458F3"\r
+            {\r
+            "UseDynamicProperties" = "11:FALSE"\r
+            "IsDependency" = "11:FALSE"\r
+            "SourcePath" = "8:<VsdDialogDir>\\VsdBasicDialogs.wim"\r
+            }\r
+            "{DF760B10-853B-4699-99F2-AFF7185B4A62}:_E310DA8CED734E00950A3C5D630CE987"\r
+            {\r
+            "Name" = "8:#1902"\r
+            "Sequence" = "3:2"\r
+            "Attributes" = "3:3"\r
+                "Dialogs"\r
+                {\r
+                    "{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_CB172E69F9C74901BE1040336CFD4F72"\r
+                    {\r
+                    "Sequence" = "3:100"\r
+                    "DisplayName" = "8:Finished"\r
+                    "UseDynamicProperties" = "11:TRUE"\r
+                    "IsDependency" = "11:FALSE"\r
+                    "SourcePath" = "8:<VsdDialogDir>\\VsdAdminFinishedDlg.wid"\r
+                        "Properties"\r
+                        {\r
+                            "BannerBitmap"\r
+                            {\r
+                            "Name" = "8:BannerBitmap"\r
+                            "DisplayName" = "8:#1001"\r
+                            "Description" = "8:#1101"\r
+                            "Type" = "3:8"\r
+                            "ContextData" = "8:Bitmap"\r
+                            "Attributes" = "3:4"\r
+                            "Setting" = "3:1"\r
+                            "UsePlugInResources" = "11:TRUE"\r
+                            }\r
+                        }\r
+                    }\r
+                }\r
+            }\r
+            "{DF760B10-853B-4699-99F2-AFF7185B4A62}:_F44F9BE9B54940848289669635E4A5A2"\r
+            {\r
+            "Name" = "8:#1901"\r
+            "Sequence" = "3:1"\r
+            "Attributes" = "3:2"\r
+                "Dialogs"\r
+                {\r
+                    "{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_14751F327A634B989283C8F28CFB6DFC"\r
+                    {\r
+                    "Sequence" = "3:100"\r
+                    "DisplayName" = "8:Progress"\r
+                    "UseDynamicProperties" = "11:TRUE"\r
+                    "IsDependency" = "11:FALSE"\r
+                    "SourcePath" = "8:<VsdDialogDir>\\VsdProgressDlg.wid"\r
+                        "Properties"\r
+                        {\r
+                            "BannerBitmap"\r
+                            {\r
+                            "Name" = "8:BannerBitmap"\r
+                            "DisplayName" = "8:#1001"\r
+                            "Description" = "8:#1101"\r
+                            "Type" = "3:8"\r
+                            "ContextData" = "8:Bitmap"\r
+                            "Attributes" = "3:4"\r
+                            "Setting" = "3:1"\r
+                            "UsePlugInResources" = "11:TRUE"\r
+                            }\r
+                            "ShowProgress"\r
+                            {\r
+                            "Name" = "8:ShowProgress"\r
+                            "DisplayName" = "8:#1009"\r
+                            "Description" = "8:#1109"\r
+                            "Type" = "3:5"\r
+                            "ContextData" = "8:1;True=1;False=0"\r
+                            "Attributes" = "3:0"\r
+                            "Setting" = "3:0"\r
+                            "Value" = "3:1"\r
+                            "DefaultValue" = "3:1"\r
+                            "UsePlugInResources" = "11:TRUE"\r
+                            }\r
+                        }\r
+                    }\r
+                }\r
+            }\r
+        }\r
+        "MergeModule"\r
+        {\r
+            "{CEE29DC0-9FBA-4B99-8D47-5BC643D9B626}:_08C93FB397914590906BDE7683F66B04"\r
+            {\r
+            "UseDynamicProperties" = "11:TRUE"\r
+            "IsDependency" = "11:TRUE"\r
+            "SourcePath" = "8:policy_9_0_Microsoft_VC90_DebugCRT_x86.msm"\r
+                "Properties"\r
+                {\r
+                }\r
+            "LanguageId" = "3:0"\r
+            "Exclude" = "11:FALSE"\r
+            "Folder" = "8:"\r
+            "Feature" = "8:"\r
+            "IsolateTo" = "8:"\r
+            }\r
+            "{CEE29DC0-9FBA-4B99-8D47-5BC643D9B626}:_3251CC1E864E41D58BDE7A6F35F2407A"\r
+            {\r
+            "UseDynamicProperties" = "11:TRUE"\r
+            "IsDependency" = "11:TRUE"\r
+            "SourcePath" = "8:microsoft_vc90_debugcrt_x86.msm"\r
+                "Properties"\r
+                {\r
+                }\r
+            "LanguageId" = "3:0"\r
+            "Exclude" = "11:FALSE"\r
+            "Folder" = "8:"\r
+            "Feature" = "8:"\r
+            "IsolateTo" = "8:"\r
+            }\r
+        }\r
+        "ProjectOutput"\r
+        {\r
+            "{5259A561-127C-4D43-A0A1-72F10C7B3BF8}:_E97571D3FBE048DABDC59B37762D800F"\r
+            {\r
+            "SourcePath" = "8:Win32\\Debug\\ipptool.exe"\r
+            "TargetName" = "8:"\r
+            "Tag" = "8:"\r
+            "Folder" = "8:_FFAEDEA1D38D4088A03FDD6F17E2CA5D"\r
+            "Condition" = "8:"\r
+            "Transitive" = "11:FALSE"\r
+            "Vital" = "11:TRUE"\r
+            "ReadOnly" = "11:FALSE"\r
+            "Hidden" = "11:FALSE"\r
+            "System" = "11:FALSE"\r
+            "Permanent" = "11:FALSE"\r
+            "SharedLegacy" = "11:FALSE"\r
+            "PackageAs" = "3:1"\r
+            "Register" = "3:1"\r
+            "Exclude" = "11:FALSE"\r
+            "IsDependency" = "11:FALSE"\r
+            "IsolateTo" = "8:"\r
+            "ProjectOutputGroupRegister" = "3:1"\r
+            "OutputConfiguration" = "8:"\r
+            "OutputGroupCanonicalName" = "8:Built"\r
+            "OutputProjectGuid" = "8:{B246D91E-61F2-4433-BFD2-6C2A96FBD4D4}"\r
+            "ShowKeyOutput" = "11:TRUE"\r
+                "ExcludeFilters"\r
+                {\r
+                }\r
+            }\r
+            "{5259A561-127C-4D43-A0A1-72F10C7B3BF8}:_EA282F32A10B4ED1A81AA6133B997C6A"\r
+            {\r
+            "SourcePath" = "8:Win32\\Debug\\libcups2.dll"\r
+            "TargetName" = "8:"\r
+            "Tag" = "8:"\r
+            "Folder" = "8:_FFAEDEA1D38D4088A03FDD6F17E2CA5D"\r
+            "Condition" = "8:"\r
+            "Transitive" = "11:FALSE"\r
+            "Vital" = "11:TRUE"\r
+            "ReadOnly" = "11:FALSE"\r
+            "Hidden" = "11:FALSE"\r
+            "System" = "11:FALSE"\r
+            "Permanent" = "11:FALSE"\r
+            "SharedLegacy" = "11:FALSE"\r
+            "PackageAs" = "3:1"\r
+            "Register" = "3:1"\r
+            "Exclude" = "11:FALSE"\r
+            "IsDependency" = "11:FALSE"\r
+            "IsolateTo" = "8:"\r
+            "ProjectOutputGroupRegister" = "3:1"\r
+            "OutputConfiguration" = "8:"\r
+            "OutputGroupCanonicalName" = "8:Built"\r
+            "OutputProjectGuid" = "8:{CB4AA6F2-3E84-45BE-B505-95CD375E8BE3}"\r
+            "ShowKeyOutput" = "11:TRUE"\r
+                "ExcludeFilters"\r
+                {\r
+                }\r
+            }\r
+        }\r
+    }\r
+}\r
index 6c59af17f1d4361e4c647800eddc52aa1dc9fd8c..cebe443aac106419b90b643c1fd6862165a23d25 100644 (file)
@@ -21,8 +21,8 @@
        <Configurations>\r
                <Configuration\r
                        Name="Debug|Win32"\r
-                       OutputDirectory="$(SolutionDir)$(ConfigurationName)"\r
-                       IntermediateDirectory="$(ConfigurationName)"\r
+                       OutputDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"\r
                        ConfigurationType="1"\r
                        CharacterSet="1"\r
                        >\r
                        />\r
                </Configuration>\r
                <Configuration\r
-                       Name="Release|Win32"\r
-                       OutputDirectory="$(SolutionDir)$(ConfigurationName)"\r
-                       IntermediateDirectory="$(ConfigurationName)"\r
+                       Name="Debug|x64"\r
+                       OutputDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"\r
                        ConfigurationType="1"\r
                        CharacterSet="1"\r
-                       WholeProgramOptimization="1"\r
                        >\r
                        <Tool\r
                                Name="VCPreBuildEventTool"\r
                        />\r
                        <Tool\r
                                Name="VCMIDLTool"\r
+                               TargetEnvironment="3"\r
                        />\r
                        <Tool\r
                                Name="VCCLCompilerTool"\r
+                               Optimization="0"\r
                                AdditionalIncludeDirectories="..\vcnet;..;..\vcnet\regex"\r
-                               PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE"\r
-                               RuntimeLibrary="2"\r
+                               PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE"\r
+                               MinimalRebuild="true"\r
+                               BasicRuntimeChecks="3"\r
+                               RuntimeLibrary="3"\r
                                UsePrecompiledHeader="0"\r
                                WarningLevel="1"\r
                                Detect64BitPortabilityProblems="false"\r
                        />\r
                        <Tool\r
                                Name="VCLinkerTool"\r
-                               LinkIncremental="1"\r
+                               LinkIncremental="2"\r
                                GenerateDebugInformation="true"\r
                                SubSystem="1"\r
-                               OptimizeReferences="2"\r
-                               EnableCOMDATFolding="2"\r
                                RandomizedBaseAddress="1"\r
                                DataExecutionPrevention="0"\r
-                               TargetMachine="1"\r
+                               TargetMachine="17"\r
                        />\r
                        <Tool\r
                                Name="VCALinkTool"\r
                        />\r
                </Configuration>\r
                <Configuration\r
-                       Name="Debug|x64"\r
-                       OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"\r
+                       Name="Release|Win32"\r
+                       OutputDirectory="$(PlatformName)\$(ConfigurationName)"\r
                        IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"\r
                        ConfigurationType="1"\r
                        CharacterSet="1"\r
+                       WholeProgramOptimization="1"\r
                        >\r
                        <Tool\r
                                Name="VCPreBuildEventTool"\r
                        />\r
                        <Tool\r
                                Name="VCMIDLTool"\r
-                               TargetEnvironment="3"\r
                        />\r
                        <Tool\r
                                Name="VCCLCompilerTool"\r
-                               Optimization="0"\r
                                AdditionalIncludeDirectories="..\vcnet;..;..\vcnet\regex"\r
-                               PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE"\r
-                               MinimalRebuild="true"\r
-                               BasicRuntimeChecks="3"\r
-                               RuntimeLibrary="3"\r
+                               PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE"\r
+                               RuntimeLibrary="2"\r
                                UsePrecompiledHeader="0"\r
                                WarningLevel="1"\r
                                Detect64BitPortabilityProblems="false"\r
                        />\r
                        <Tool\r
                                Name="VCLinkerTool"\r
-                               LinkIncremental="2"\r
+                               LinkIncremental="1"\r
                                GenerateDebugInformation="true"\r
                                SubSystem="1"\r
+                               OptimizeReferences="2"\r
+                               EnableCOMDATFolding="2"\r
                                RandomizedBaseAddress="1"\r
                                DataExecutionPrevention="0"\r
-                               TargetMachine="17"\r
+                               TargetMachine="1"\r
                        />\r
                        <Tool\r
                                Name="VCALinkTool"\r
                </Configuration>\r
                <Configuration\r
                        Name="Release|x64"\r
-                       OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"\r
+                       OutputDirectory="$(PlatformName)\$(ConfigurationName)"\r
                        IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"\r
                        ConfigurationType="1"\r
                        CharacterSet="1"\r
index 070dd6b1c52eae4d815d00e3df17f5427825d519..417721930bb86b2dca601a18cc5f71b4f105bbbc 100644 (file)
@@ -17,8 +17,8 @@
        <Configurations>\r
                <Configuration\r
                        Name="Debug|Win32"\r
-                       OutputDirectory="Debug"\r
-                       IntermediateDirectory="Debug"\r
+                       OutputDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"\r
                        ConfigurationType="1"\r
                        InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"\r
                        CharacterSet="2"\r
@@ -62,7 +62,7 @@
                        />\r
                        <Tool\r
                                Name="VCLinkerTool"\r
-                               OutputFile="Debug\testfile.exe"\r
+                               OutputFile="$(OutDir)\testfile.exe"\r
                                LinkIncremental="2"\r
                                GenerateDebugInformation="true"\r
                                ProgramDatabaseFile="$(OutDir)/testfile.pdb"\r
@@ -95,8 +95,8 @@
                </Configuration>\r
                <Configuration\r
                        Name="Release|Win32"\r
-                       OutputDirectory="Release"\r
-                       IntermediateDirectory="Release"\r
+                       OutputDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"\r
                        ConfigurationType="1"\r
                        InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"\r
                        CharacterSet="2"\r
                        />\r
                        <Tool\r
                                Name="VCLinkerTool"\r
-                               OutputFile="testfile.exe"\r
+                               OutputFile="$(OutDir)\testfile.exe"\r
                                LinkIncremental="1"\r
                                GenerateDebugInformation="true"\r
                                SubSystem="1"\r
index c041ebb7539af3daa3c95940c3bfc2371562f76c..49df7226184b88bd7daee072f70dbcedc36e925e 100755 (executable)
@@ -17,8 +17,8 @@
        <Configurations>\r
                <Configuration\r
                        Name="Debug|Win32"\r
-                       OutputDirectory="Debug"\r
-                       IntermediateDirectory="Debug"\r
+                       OutputDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"\r
                        ConfigurationType="1"\r
                        InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"\r
                        CharacterSet="2"\r
@@ -62,7 +62,7 @@
                        />\r
                        <Tool\r
                                Name="VCLinkerTool"\r
-                               OutputFile="Debug\testhttp.exe"\r
+                               OutputFile="$(OutDir)\testhttp.exe"\r
                                LinkIncremental="2"\r
                                GenerateDebugInformation="true"\r
                                ProgramDatabaseFile="$(OutDir)/testhttp.pdb"\r
@@ -95,8 +95,8 @@
                </Configuration>\r
                <Configuration\r
                        Name="Release|Win32"\r
-                       OutputDirectory="Release"\r
-                       IntermediateDirectory="Release"\r
+                       OutputDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"\r
                        ConfigurationType="1"\r
                        InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"\r
                        CharacterSet="2"\r
                        />\r
                        <Tool\r
                                Name="VCLinkerTool"\r
-                               OutputFile="testhttp.exe"\r
+                               OutputFile="$(OutDir)\testhttp.exe"\r
                                LinkIncremental="1"\r
                                GenerateDebugInformation="true"\r
                                SubSystem="1"\r