aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilip P. Moltmann <moltmann@google.com>2018-03-16 14:38:27 -0700
committerPhilip P. Moltmann <moltmann@google.com>2018-03-19 09:16:29 -0700
commit985548d9a7de8cde72ea0b5a81f6f0854d049454 (patch)
treef82a2c6d750e2ab5873e0ab6a1b71cd7a2631e1f
parentcbcd27119edc01ce3009d6a90d47abf2d486b61d (diff)
downloadlibcups-pie-qpr1-s1-release.tar.gz
Test: Printed a page using this library (using the default print service) Fixes: 71766736 Change-Id: I24874e9b4c95102c5d9a0d709326748c0433ca24
-rw-r--r--config.h4
-rw-r--r--cups/Makefile118
-rw-r--r--cups/api-array.header32
-rw-r--r--cups/api-array.shtml194
-rw-r--r--cups/api-cups.header38
-rw-r--r--cups/api-cups.shtml441
-rw-r--r--cups/api-filedir.header34
-rw-r--r--cups/api-filedir.shtml29
-rw-r--r--cups/api-httpipp.header37
-rw-r--r--cups/api-httpipp.shtml315
-rw-r--r--cups/auth.c2
-rw-r--r--cups/cups-private.h4
-rw-r--r--cups/cups.h48
-rw-r--r--cups/cupspm-icon.png0
-rw-r--r--cups/cupspm.md994
-rw-r--r--cups/cupspm.opacity0
-rw-r--r--cups/cupspm.png0
-rw-r--r--cups/dest-job.c34
-rw-r--r--cups/dest-localization.c50
-rw-r--r--cups/dest-options.c90
-rw-r--r--cups/dest.c1390
-rw-r--r--cups/dir.c31
-rw-r--r--cups/encode.c6
-rw-r--r--cups/file-private.h4
-rw-r--r--cups/file.c39
-rw-r--r--cups/file.h4
-rw-r--r--cups/http-addr.c12
-rw-r--r--cups/http-addrlist.c21
-rw-r--r--cups/http-private.h28
-rw-r--r--cups/http-support.c28
-rw-r--r--cups/http.c55
-rw-r--r--cups/http.h9
-rw-r--r--cups/ipp-support.c6
-rw-r--r--cups/ipp.c186
-rw-r--r--cups/ipp.h273
-rw-r--r--cups/language.c72
-rw-r--r--cups/language.h2
-rw-r--r--cups/options.c64
-rw-r--r--cups/ppd-cache.c207
-rw-r--r--cups/ppd-mark.c16
-rw-r--r--cups/pwg-media.c1
-rw-r--r--cups/pwg.h6
-rw-r--r--cups/request.c34
-rw-r--r--cups/snmp.c4
-rw-r--r--cups/string.c7
-rw-r--r--cups/testcups.c47
-rw-r--r--cups/testdest.c66
-rw-r--r--cups/testgetdests.c51
-rw-r--r--cups/testipp.c160
-rw-r--r--cups/testlang.c149
-rw-r--r--cups/thread-private.h3
-rw-r--r--cups/thread.c25
-rw-r--r--cups/tls-darwin.c44
-rw-r--r--cups/tls-gnutls.c25
-rw-r--r--cups/tls-sspi.c7
-rw-r--r--cups/tlscheck.c12
-rw-r--r--cups/usersys.c20
-rw-r--r--cups/util.c125
-rw-r--r--cups/versioning.h16
-rw-r--r--filter/Makefile36
-rw-r--r--filter/testclient.c960
-rw-r--r--libcups_version2
62 files changed, 4309 insertions, 2408 deletions
diff --git a/config.h b/config.h
index 2decf312..28fe0344 100644
--- a/config.h
+++ b/config.h
@@ -17,8 +17,8 @@
#ifndef _CUPS_CONFIG_H_
#define _CUPS_CONFIG_H_
-#define CUPS_SVERSION "CUPS v2.2.3"
-#define CUPS_MINIMAL "CUPS/2.2.3"
+#define CUPS_SVERSION "CUPS v2.2.6"
+#define CUPS_MINIMAL "CUPS/2.2.6"
#define CUPS_DEFAULT_PRINTOPERATOR_AUTH "@SYSTEM"
#define CUPS_DEFAULT_LOG_LEVEL "warn"
#define CUPS_DEFAULT_BROWSE_LOCAL_PROTOCOLS "dnssd"
diff --git a/cups/Makefile b/cups/Makefile
index 1df7d855..9a220c85 100644
--- a/cups/Makefile
+++ b/cups/Makefile
@@ -1,7 +1,7 @@
#
-# API library Makefile for CUPS.
+# Library Makefile for CUPS.
#
-# Copyright 2007-2016 by Apple Inc.
+# Copyright 2007-2017 by Apple Inc.
# Copyright 1997-2006 by Easy Software Products, all rights reserved.
#
# These coded instructions, statements, and computer programs are the
@@ -89,6 +89,7 @@ TESTOBJS = \
testcups.o \
testdest.o \
testfile.o \
+ testgetdests.o \
testhttp.o \
testi18n.o \
testipp.o \
@@ -158,6 +159,7 @@ UNITTARGETS = \
testcups \
testdest \
testfile \
+ testgetdests \
testhttp \
testi18n \
testipp \
@@ -344,7 +346,7 @@ libcups.2.dylib: $(LIBOBJS) $(LIBCUPSORDER)
libcups.la: $(LIBOBJS)
echo Linking $@...
- $(CC) $(ARCHFLAGS) $(DSOFLAGS) -o $@ $(LIBOBJS:.o=.lo) \
+ $(LD_CC) $(ARCHFLAGS) $(DSOFLAGS) -o $@ $(LIBOBJS:.o=.lo) \
-rpath $(LIBDIR) -version-info 2:12 $(LIBGSSAPI) $(SSLLIBS) \
$(DNSSDLIBS) $(COMMONLIBS) $(LIBZ)
@@ -383,7 +385,7 @@ libcups2.def: $(LIBOBJS) Makefile
testadmin: testadmin.o $(LIBCUPSSTATIC)
echo Linking $@...
- $(CC) $(LDFLAGS) -o $@ testadmin.o $(LIBCUPSSTATIC) \
+ $(LD_CC) $(LDFLAGS) -o $@ testadmin.o $(LIBCUPSSTATIC) \
$(LIBGSSAPI) $(SSLLIBS) $(DNSSDLIBS) $(COMMONLIBS) $(LIBZ)
@@ -393,7 +395,7 @@ testadmin: testadmin.o $(LIBCUPSSTATIC)
testarray: testarray.o $(LIBCUPSSTATIC)
echo Linking $@...
- $(CC) $(ARCHFLAGS) $(LDFLAGS) -o $@ testarray.o $(LIBCUPSSTATIC) \
+ $(LD_CC) $(ARCHFLAGS) $(LDFLAGS) -o $@ testarray.o $(LIBCUPSSTATIC) \
$(LIBGSSAPI) $(SSLLIBS) $(DNSSDLIBS) $(COMMONLIBS) $(LIBZ)
echo Running array API tests...
./testarray
@@ -405,7 +407,7 @@ testarray: testarray.o $(LIBCUPSSTATIC)
testcache: testcache.o $(LIBCUPSSTATIC)
echo Linking $@...
- $(CC) $(LDFLAGS) -o $@ testcache.o $(LIBCUPSSTATIC) \
+ $(LD_CC) $(LDFLAGS) -o $@ testcache.o $(LIBCUPSSTATIC) \
$(LIBGSSAPI) $(SSLLIBS) $(DNSSDLIBS) $(COMMONLIBS) $(LIBZ)
@@ -415,7 +417,7 @@ testcache: testcache.o $(LIBCUPSSTATIC)
testconflicts: testconflicts.o $(LIBCUPSSTATIC)
echo Linking $@...
- $(CC) $(LDFLAGS) -o $@ testconflicts.o $(LIBCUPSSTATIC) \
+ $(LD_CC) $(LDFLAGS) -o $@ testconflicts.o $(LIBCUPSSTATIC) \
$(LIBGSSAPI) $(SSLLIBS) $(DNSSDLIBS) $(COMMONLIBS) $(LIBZ)
@@ -425,7 +427,7 @@ testconflicts: testconflicts.o $(LIBCUPSSTATIC)
testcreds: testcreds.o $(LIBCUPSSTATIC)
echo Linking $@...
- $(CC) $(ARCHFLAGS) $(LDFLAGS) -o $@ testcreds.o $(LIBCUPSSTATIC) \
+ $(LD_CC) $(ARCHFLAGS) $(LDFLAGS) -o $@ testcreds.o $(LIBCUPSSTATIC) \
$(LIBGSSAPI) $(SSLLIBS) $(DNSSDLIBS) $(COMMONLIBS) $(LIBZ)
@@ -435,7 +437,7 @@ testcreds: testcreds.o $(LIBCUPSSTATIC)
testcups: testcups.o $(LIBCUPSSTATIC)
echo Linking $@...
- $(CC) $(LDFLAGS) -o $@ testcups.o $(LIBCUPSSTATIC) \
+ $(LD_CC) $(LDFLAGS) -o $@ testcups.o $(LIBCUPSSTATIC) \
$(LIBGSSAPI) $(SSLLIBS) $(DNSSDLIBS) $(COMMONLIBS) $(LIBZ)
@@ -445,7 +447,7 @@ testcups: testcups.o $(LIBCUPSSTATIC)
testdest: testdest.o $(LIBCUPSSTATIC)
echo Linking $@...
- $(CC) $(LDFLAGS) -o $@ testdest.o $(LIBCUPSSTATIC) \
+ $(LD_CC) $(LDFLAGS) -o $@ testdest.o $(LIBCUPSSTATIC) \
$(LIBGSSAPI) $(SSLLIBS) $(DNSSDLIBS) $(COMMONLIBS) $(LIBZ)
@@ -455,19 +457,29 @@ testdest: testdest.o $(LIBCUPSSTATIC)
testfile: testfile.o $(LIBCUPSSTATIC)
echo Linking $@...
- $(CC) $(ARCHFLAGS) $(LDFLAGS) -o $@ testfile.o $(LIBCUPSSTATIC) \
+ $(LD_CC) $(ARCHFLAGS) $(LDFLAGS) -o $@ testfile.o $(LIBCUPSSTATIC) \
$(LIBGSSAPI) $(SSLLIBS) $(DNSSDLIBS) $(COMMONLIBS) $(LIBZ)
echo Running file API tests...
./testfile
#
+# testgetdests (dependency on static CUPS library is intentional)
+#
+
+testgetdests: testgetdests.o $(LIBCUPSSTATIC)
+ echo Linking $@...
+ $(LD_CC) $(LDFLAGS) -o $@ testgetdests.o $(LIBCUPSSTATIC) \
+ $(LIBGSSAPI) $(SSLLIBS) $(DNSSDLIBS) $(COMMONLIBS) $(LIBZ)
+
+
+#
# testhttp (dependency on static CUPS library is intentional)
#
testhttp: testhttp.o $(LIBCUPSSTATIC)
echo Linking $@...
- $(CC) $(ARCHFLAGS) $(LDFLAGS) -o $@ testhttp.o $(LIBCUPSSTATIC) \
+ $(LD_CC) $(ARCHFLAGS) $(LDFLAGS) -o $@ testhttp.o $(LIBCUPSSTATIC) \
$(LIBGSSAPI) $(SSLLIBS) $(DNSSDLIBS) $(COMMONLIBS) $(LIBZ)
echo Running HTTP API tests...
./testhttp
@@ -479,7 +491,7 @@ testhttp: testhttp.o $(LIBCUPSSTATIC)
testipp: testipp.o $(LIBCUPSSTATIC)
echo Linking $@...
- $(CC) $(ARCHFLAGS) $(LDFLAGS) -o $@ testipp.o $(LIBCUPSSTATIC) \
+ $(LD_CC) $(ARCHFLAGS) $(LDFLAGS) -o $@ testipp.o $(LIBCUPSSTATIC) \
$(LIBGSSAPI) $(SSLLIBS) $(DNSSDLIBS) $(COMMONLIBS) $(LIBZ)
echo Running IPP API tests...
./testipp
@@ -491,7 +503,7 @@ testipp: testipp.o $(LIBCUPSSTATIC)
testi18n: testi18n.o $(LIBCUPSSTATIC)
echo Linking $@...
- $(CC) $(ARCHFLAGS) $(LDFLAGS) -o $@ testi18n.o $(LIBCUPSSTATIC) \
+ $(LD_CC) $(ARCHFLAGS) $(LDFLAGS) -o $@ testi18n.o $(LIBCUPSSTATIC) \
$(LIBGSSAPI) $(SSLLIBS) $(DNSSDLIBS) $(COMMONLIBS) $(LIBZ)
echo Running internationalization API tests...
./testi18n
@@ -503,10 +515,22 @@ testi18n: testi18n.o $(LIBCUPSSTATIC)
testlang: testlang.o $(LIBCUPSSTATIC)
echo Linking $@...
- $(CC) $(ARCHFLAGS) $(LDFLAGS) -o $@ testlang.o $(LIBCUPSSTATIC) \
+ $(LD_CC) $(ARCHFLAGS) $(LDFLAGS) -o $@ testlang.o $(LIBCUPSSTATIC) \
$(LIBGSSAPI) $(SSLLIBS) $(DNSSDLIBS) $(COMMONLIBS) $(LIBZ)
+ echo Creating locale directory structure...
+ $(RM) -r locale
+ $(MKDIR) locale/en
+ echo 'msgid "No"' > locale/en/cups_en.po
+ echo 'msgstr "No"' >> locale/en/cups_en.po
+ echo 'msgid "Yes"' >> locale/en/cups_en.po
+ echo 'msgstr "Yes"' >> locale/en/cups_en.po
+ for po in ../locale/cups_*.po; do \
+ lang=`basename $$po .po | sed -e '1,$$s/^cups_//'`; \
+ $(MKDIR) locale/$$lang; \
+ $(LN) ../../$$po locale/$$lang; \
+ done
echo Running language API tests...
- ./testlang
+ LOCALEDIR=locale ./testlang
#
@@ -515,7 +539,7 @@ testlang: testlang.o $(LIBCUPSSTATIC)
testoptions: testoptions.o $(LIBCUPSSTATIC)
echo Linking $@...
- $(CC) $(ARCHFLAGS) $(LDFLAGS) -o $@ testoptions.o $(LIBCUPSSTATIC) \
+ $(LD_CC) $(ARCHFLAGS) $(LDFLAGS) -o $@ testoptions.o $(LIBCUPSSTATIC) \
$(LIBGSSAPI) $(SSLLIBS) $(DNSSDLIBS) $(COMMONLIBS) $(LIBZ)
echo Running option API tests...
./testoptions
@@ -527,7 +551,7 @@ testoptions: testoptions.o $(LIBCUPSSTATIC)
testppd: testppd.o $(LIBCUPSSTATIC) test.ppd test2.ppd
echo Linking $@...
- $(CC) $(ARCHFLAGS) $(LDFLAGS) -o $@ testppd.o $(LIBCUPSSTATIC) \
+ $(LD_CC) $(ARCHFLAGS) $(LDFLAGS) -o $@ testppd.o $(LIBCUPSSTATIC) \
$(LIBGSSAPI) $(SSLLIBS) $(DNSSDLIBS) $(COMMONLIBS) $(LIBZ)
echo Running PPD API tests...
./testppd
@@ -539,7 +563,7 @@ testppd: testppd.o $(LIBCUPSSTATIC) test.ppd test2.ppd
testpwg: testpwg.o $(LIBCUPSSTATIC) test.ppd
echo Linking $@...
- $(CC) $(ARCHFLAGS) $(LDFLAGS) -o $@ testpwg.o $(LIBCUPSSTATIC) \
+ $(LD_CC) $(ARCHFLAGS) $(LDFLAGS) -o $@ testpwg.o $(LIBCUPSSTATIC) \
$(LIBGSSAPI) $(SSLLIBS) $(DNSSDLIBS) $(COMMONLIBS) $(LIBZ)
echo Running PWG API tests...
./testpwg test.ppd
@@ -551,7 +575,7 @@ testpwg: testpwg.o $(LIBCUPSSTATIC) test.ppd
testsnmp: testsnmp.o $(LIBCUPSSTATIC)
echo Linking $@...
- $(CC) $(LDFLAGS) -o $@ testsnmp.o $(LIBCUPSSTATIC) \
+ $(LD_CC) $(LDFLAGS) -o $@ testsnmp.o $(LIBCUPSSTATIC) \
$(LIBGSSAPI) $(SSLLIBS) $(DNSSDLIBS) $(COMMONLIBS) $(LIBZ)
@@ -561,7 +585,7 @@ testsnmp: testsnmp.o $(LIBCUPSSTATIC)
tlscheck: tlscheck.o $(LIBCUPSSTATIC)
echo Linking $@...
- $(CC) $(ARCHFLAGS) $(LDFLAGS) -o $@ tlscheck.o $(LIBCUPSSTATIC) \
+ $(LD_CC) $(ARCHFLAGS) $(LDFLAGS) -o $@ tlscheck.o $(LIBCUPSSTATIC) \
$(LIBGSSAPI) $(SSLLIBS) $(DNSSDLIBS) $(COMMONLIBS) $(LIBZ)
@@ -571,56 +595,27 @@ tlscheck: tlscheck.o $(LIBCUPSSTATIC)
apihelp:
echo Generating CUPS API help files...
- mxmldoc --section "Programming" \
- --title "Introduction to CUPS Programming" \
- --css ../doc/cups-printable.css \
- --header api-overview.header --intro api-overview.shtml \
- >../doc/help/api-overview.html
+ $(RM) cupspm.xml
+ mxmldoc --section "Programming" --body cupspm.md \
+ cupspm.xml \
+ auth.c cups.h dest*.c encode.c http.h http*.c ipp.h ipp*.c \
+ options.c tls-darwin.c usersys.c util.c \
+ --coverimage cupspm.png \
+ --epub ../doc/help/cupspm.epub
+ mxmldoc --section "Programming" --body cupspm.md \
+ cupspm.xml > ../doc/help/cupspm.html
+ $(RM) cupspm.xml
mxmldoc --section "Programming" --title "Administration APIs" \
--css ../doc/cups-printable.css \
--header api-admin.header --intro api-admin.shtml \
api-admin.xml \
adminutil.c adminutil.h getdevices.c >../doc/help/api-admin.html
- mxmldoc --tokens help/api-admin.html api-admin.xml >../doc/help/api-admin.tokens
$(RM) api-admin.xml
- mxmldoc --section "Programming" --title "Array API" \
- --css ../doc/cups-printable.css \
- --header api-array.header --intro api-array.shtml \
- api-array.xml \
- array.h array.c >../doc/help/api-array.html
- mxmldoc --tokens help/api-array.html api-array.xml >../doc/help/api-array.tokens
- $(RM) api-array.xml
- mxmldoc --section "Programming" --title "CUPS API" \
- --css ../doc/cups-printable.css \
- --header api-cups.header --intro api-cups.shtml \
- api-cups.xml \
- cups.h pwg.h adminutil.c dest*.c language.c notify.c \
- options.c pwg-media.c tempfile.c usersys.c \
- util.c >../doc/help/api-cups.html
- mxmldoc --tokens help/api-cups.html api-cups.xml >../doc/help/api-cups.tokens
- $(RM) api-cups.xml
- mxmldoc --section "Programming" --title "File and Directory APIs" \
- --css ../doc/cups-printable.css \
- --header api-filedir.header --intro api-filedir.shtml \
- api-filedir.xml \
- 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 (DEPRECATED)" \
--css ../doc/cups-printable.css \
--header api-ppd.header --intro api-ppd.shtml \
api-ppd.xml ppd.h ppd-*.c >../doc/help/api-ppd.html
- mxmldoc --tokens help/api-ppd.html api-ppd.xml >../doc/help/api-ppd.tokens
$(RM) api-ppd.xml
- mxmldoc --section "Programming" --title "HTTP and IPP APIs" \
- --css ../doc/cups-printable.css \
- --header api-httpipp.header --intro api-httpipp.shtml \
- api-httpipp.xml \
- http.h ipp.h auth.c getdevices.c getputfile.c encode.c \
- http.c http-addr.c http-support.c ipp.c ipp-support.c \
- md5passwd.c request.c >../doc/help/api-httpipp.html
- mxmldoc --tokens help/api-httpipp.html api-httpipp.xml >../doc/help/api-httpipp.tokens
- $(RM) api-httpipp.xml
mxmldoc --section "Programming" \
--title "Filter and Backend Programming" \
--css ../doc/cups-printable.css \
@@ -628,7 +623,6 @@ apihelp:
api-filter.xml \
backchannel.c backend.h backend.c sidechannel.c sidechannel.h \
>../doc/help/api-filter.html
- mxmldoc --tokens help/api-filter.html api-filter.xml >../doc/help/api-filter.tokens
$(RM) api-filter.xml
@@ -637,8 +631,6 @@ apihelp:
#
sloc:
- echo "libcupslite: \c"
- sloccount $(LITEOBJS:.o=.c) 2>/dev/null | grep "Total Physical" | awk '{print $$9}'
echo "libcups: \c"
sloccount $(LIBOBJS:.o=.c) 2>/dev/null | grep "Total Physical" | awk '{print $$9}'
diff --git a/cups/api-array.header b/cups/api-array.header
deleted file mode 100644
index 557833e5..00000000
--- a/cups/api-array.header
+++ /dev/null
@@ -1,32 +0,0 @@
-<!--
- Array API header for CUPS.
-
- Copyright 2008-2011 by Apple Inc.
-
- 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/".
--->
-
-<h1 class='title'>Array API</h1>
-
-<div class='summary'><table summary='General Information'>
-<thead>
-<tr>
- <th>Header</th>
- <th>cups/array.h</th>
-</tr>
-</thead>
-<tbody>
-<tr>
- <th>Library</th>
- <td>-lcups</td>
-</tr>
-<tr>
- <th>See Also</th>
- <td>Programming: <a href='api-overview.html' target='_top'>Introduction to CUPS Programming</a></td>
-</tr>
-</tbody>
-</table></div>
diff --git a/cups/api-array.shtml b/cups/api-array.shtml
deleted file mode 100644
index 374ef5bf..00000000
--- a/cups/api-array.shtml
+++ /dev/null
@@ -1,194 +0,0 @@
-<!--
- Array API introduction 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/".
--->
-
-<h2 class='title'><a name='OVERVIEW'>Overview</a></h2>
-
-<p>The CUPS array API provides a high-performance generic array container.
-The contents of the array container can be sorted and the container itself is
-designed for optimal speed and memory usage under a wide variety of conditions.
-Sorted arrays use a binary search algorithm from the last found or inserted
-element to quickly find matching elements in the array. Arrays created with the
-optional hash function can often find elements with a single lookup. The
-<a href='#cups_array_t'><code>cups_array_t</code></a> type is used when
-referring to a CUPS array.</p>
-
-<p>The CUPS scheduler (<tt>cupsd</tt>) and many of the CUPS API
-functions use the array API to efficiently manage large lists of
-data.</p>
-
-<h3><a name='MANAGING_ARRAYS'>Managing Arrays</a></h3>
-
-<p>Arrays are created using either the
-<a href='#cupsArrayNew'><code>cupsArrayNew</code></a>,
-<a href='#cupsArrayNew2'><code>cupsArrayNew2</code></a>, or
-<a href='#cupsArrayNew2'><code>cupsArrayNew3</code></a> functions. The
-first function creates a new array with the specified callback function
-and user data pointer:</p>
-
-<pre class='example'>
-#include &lt;cups/array.h&gt;
-
-static int compare_func(void *first, void *second, void *user_data);
-
-void *user_data;
-<a href='#cups_array_t'>cups_array_t</a> *array = <a href='#cupsArrayNew'>cupsArrayNew</a>(compare_func, user_data);
-</pre>
-
-<p>The comparison function (type
-<a href="#cups_arrayfunc_t"><code>cups_arrayfunc_t</code></a>) is called
-whenever an element is added to the array and can be <code>NULL</code> to
-create an unsorted array. The function returns -1 if the first element should
-come before the second, 0 if the first and second elements should have the same
-ordering, and 1 if the first element should come after the second.</p>
-
-<p>The "user_data" pointer is passed to your comparison function. Pass
-<code>NULL</code> if you do not need to associate the elements in your array
-with additional information.</p>
-
-<p>The <a href='#cupsArrayNew2'><code>cupsArrayNew2</code></a> function adds
-two more arguments to support hashed lookups, which can potentially provide
-instantaneous ("O(1)") lookups in your array:</p>
-
-<pre class='example'>
-#include &lt;cups/array.h&gt;
-
-#define HASH_SIZE 512 /* Size of hash table */
-
-static int compare_func(void *first, void *second, void *user_data);
-static int hash_func(void *element, void *user_data);
-
-void *user_data;
-<a href='#cups_array_t'>cups_array_t</a> *hash_array = <a href='#cupsArrayNew2'>cupsArrayNew2</a>(compare_func, user_data, hash_func, HASH_SIZE);
-</pre>
-
-<p>The hash function (type
-<a href="#cups_ahash_func_t"><code>cups_ahash_func_t</code></a>) should return a
-number from 0 to (hash_size-1) that (hopefully) uniquely identifies the
-element and is called whenever you look up an element in the array with
-<a href='#cupsArrayFind'><code>cupsArrayFind</code></a>. The hash size is
-only limited by available memory, but generally should not be larger than
-16384 to realize any performance improvement.</p>
-
-<p>The <a href='#cupsArrayNew3'><code>cupsArrayNew3</code></a> function adds
-copy and free callbacks to support basic memory management of elements:</p>
-
-<pre class='example'>
-#include &lt;cups/array.h&gt;
-
-#define HASH_SIZE 512 /* Size of hash table */
-
-static int compare_func(void *first, void *second, void *user_data);
-static void *copy_func(void *element, void *user_data);
-static void free_func(void *element, void *user_data);
-static int hash_func(void *element, void *user_data);
-
-void *user_data;
-<a href='#cups_array_t'>cups_array_t</a> *array = <a href='#cupsArrayNew3'>cupsArrayNew3</a>(compare_func, user_data, NULL, 0, copy_func, free_func);
-
-<a href='#cups_array_t'>cups_array_t</a> *hash_array = <a href='#cupsArrayNew3'>cupsArrayNew3</a>(compare_func, user_data, hash_func, HASH_SIZE, copy_func, free_func);
-</pre>
-
-<p>Once you have created the array, you add elements using the
-<a href='#cupsArrayAdd'><code>cupsArrayAdd</code></a>
-<a href='#cupsArrayInsert'><code>cupsArrayInsert</code></a> functions.
-The first function adds an element to the array, adding the new element
-after any elements that have the same order, while the second inserts the
-element before others with the same order. For unsorted arrays,
-<a href='#cupsArrayAdd'><code>cupsArrayAdd</code></a> appends the element to
-the end of the array while
-<a href='#cupsArrayInsert'><code>cupsArrayInsert</code></a> inserts the
-element at the beginning of the array. For example, the following code
-creates a sorted array of character strings:</p>
-
-<pre class='example'>
-#include &lt;cups/array.h&gt;
-
-/* Use strcmp() to compare strings - it will ignore the user_data pointer */
-<a href='#cups_array_t'>cups_array_t</a> *array = <a href='#cupsArrayNew'>cupsArrayNew</a>((<a href='#cups_array_func_t'>cups_array_func_t</a>)strcmp, NULL);
-
-/* Add four strings to the array */
-<a href='#cupsArrayAdd'>cupsArrayAdd</a>(array, "One Fish");
-<a href='#cupsArrayAdd'>cupsArrayAdd</a>(array, "Two Fish");
-<a href='#cupsArrayAdd'>cupsArrayAdd</a>(array, "Red Fish");
-<a href='#cupsArrayAdd'>cupsArrayAdd</a>(array, "Blue Fish");
-</pre>
-
-<p>Elements are removed using the
-<a href='#cupsArrayRemove'><code>cupsArrayRemove</code></a> function, for
-example:</p>
-
-<pre class='example'>
-#include &lt;cups/array.h&gt;
-
-/* Use strcmp() to compare strings - it will ignore the user_data pointer */
-<a href='#cups_array_t'>cups_array_t</a> *array = <a href='#cupsArrayNew'>cupsArrayNew</a>((<a href='#cups_array_func_t'>cups_array_func_t</a>)strcmp, NULL);
-
-/* Add four strings to the array */
-<a href='#cupsArrayAdd'>cupsArrayAdd</a>(array, "One Fish");
-<a href='#cupsArrayAdd'>cupsArrayAdd</a>(array, "Two Fish");
-<a href='#cupsArrayAdd'>cupsArrayAdd</a>(array, "Red Fish");
-<a href='#cupsArrayAdd'>cupsArrayAdd</a>(array, "Blue Fish");
-
-/* Remove "Red Fish" */
-<a href='#cupsArrayRemove'>cupsArrayRemove</a>(array, "Red Fish");
-</pre>
-
-<p>Finally, you free the memory used by the array using the
-<a href='#cupsArrayDelete'><code>cupsArrayDelete</code></a> function. All
-of the memory for the array and hash table (if any) is freed, however <em>CUPS
-does not free the elements unless you provide copy and free functions</em>.</p>
-
-<h3><a name='FINDING_AND_ENUMERATING'>Finding and Enumerating Elements</a></h3>
-
-<p>CUPS provides several functions to find and enumerate elements in an
-array. Each one sets or updates a "current index" into the array, such that
-future lookups will start where the last one left off:</p>
-
-<dl>
- <dt><a href='#cupsArrayFind'><code>cupsArrayFind</code></a></dt>
- <dd>Returns the first matching element.</dd>
- <dt><a href='#cupsArrayFirst'><code>cupsArrayFirst</code></a></dt>
- <dd>Returns the first element in the array.</dd>
- <dt><a href='#cupsArrayIndex'><code>cupsArrayIndex</code></a></dt>
- <dd>Returns the Nth element in the array, starting at 0.</dd>
- <dt><a href='#cupsArrayLast'><code>cupsArrayLast</code></a></dt>
- <dd>Returns the last element in the array.</dd>
- <dt><a href='#cupsArrayNext'><code>cupsArrayNext</code></a></dt>
- <dd>Returns the next element in the array.</dd>
- <dt><a href='#cupsArrayPrev'><code>cupsArrayPrev</code></a></dt>
- <dd>Returns the previous element in the array.</dd>
-</dl>
-
-<p>Each of these functions returns <code>NULL</code> when there is no
-corresponding element. For example, a simple <code>for</code> loop using the
-<a href='#cupsArrayFirst'><code>cupsArrayFirst</code></a> and
-<a href='#cupsArrayNext'><code>cupsArrayNext</code></a> functions will
-enumerate all of the strings in our previous example:</p>
-
-<pre class='example'>
-#include &lt;cups/array.h&gt;
-
-/* Use strcmp() to compare strings - it will ignore the user_data pointer */
-<a href='#cups_array_t'>cups_array_t</a> *array = <a href='#cupsArrayNew'>cupsArrayNew</a>((<a href='#cups_array_func_t'>cups_array_func_t</a>)strcmp, NULL);
-
-/* Add four strings to the array */
-<a href='#cupsArrayAdd'>cupsArrayAdd</a>(array, "One Fish");
-<a href='#cupsArrayAdd'>cupsArrayAdd</a>(array, "Two Fish");
-<a href='#cupsArrayAdd'>cupsArrayAdd</a>(array, "Red Fish");
-<a href='#cupsArrayAdd'>cupsArrayAdd</a>(array, "Blue Fish");
-
-/* Show all of the strings in the array */
-char *s;
-for (s = (char *)<a href='#cupsArrayFirst'>cupsArrayFirst</a>(array); s != NULL; s = (char *)<a href='#cupsArrayNext'>cupsArrayNext</a>(array))
- puts(s);
-</pre>
diff --git a/cups/api-cups.header b/cups/api-cups.header
deleted file mode 100644
index 23b3794d..00000000
--- a/cups/api-cups.header
+++ /dev/null
@@ -1,38 +0,0 @@
-<!--
- CUPS API header for CUPS.
-
- Copyright 2008-2011 by Apple Inc.
-
- 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/".
--->
-
-<h1 class='title'>CUPS API</h1>
-
-<div class='summary'><table summary='General Information'>
-<thead>
-<tr>
- <th>Header</th>
- <th>cups/cups.h</th>
-</tr>
-</thead>
-<tbody>
-<tr>
- <th>Library</th>
- <td>-lcups</td>
-</tr>
-<tr>
- <th>See Also</th>
- <td>Programming: <a href='api-overview.html' target='_top'>Introduction to CUPS Programming</a><br>
- Programming: <a href='api-array.html' target='_top'>Array API</a><br>
- Programming: <a href='api-filedir.html' target='_top'>File and Directory APIs</a><br>
- Programming: <a href='api-filter.html' target='_top'>Filter and Backend Programming</a><br>
- Programming: <a href='api-httpipp.html' target='_top'>HTTP and IPP APIs</a><br>
- Programming: <a href='api-ppd.html' target='_top'>PPD API</a><br>
- Programming: <a href='api-raster.html' target='_top'>Raster API</a></td>
-</tr>
-</tbody>
-</table></div>
diff --git a/cups/api-cups.shtml b/cups/api-cups.shtml
deleted file mode 100644
index 918efe77..00000000
--- a/cups/api-cups.shtml
+++ /dev/null
@@ -1,441 +0,0 @@
-<!--
- API introduction for CUPS.
-
- Copyright 2007-2013 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/".
--->
-
-<h2 class='title'><a name='OVERVIEW'>Overview</a></h2>
-
-<p>The CUPS API provides the convenience functions needed to support
-applications, filters, printer drivers, and backends that need to interface
-with the CUPS scheduler.</p>
-
-<h3><a name='CLIENTS_AND_SERVERS'>Clients and Servers</a></h3>
-
-<p>CUPS is based on the Internet Printing Protocol ("IPP"), which allows
-clients (applications) to communicate with a server (the scheduler) to get a
-list of printers, send print jobs, and so forth. You identify which server
-you want to communicate with using a pointer to the opaque structure
-<code>http_t</code>. All of the examples in this document use the
-<code>CUPS_HTTP_DEFAULT</code> constant, referring to the default connection
-to the scheduler. The <a href='api-httpipp.html' target='_top'>HTTP and IPP
-APIs</a> document provides more information on server connections.</p>
-
-<h3><a name='PRINTERS_AND_CLASSES'>Printers and Classes</a></h3>
-
-<p>Printers and classes (collections of printers) are accessed through
-the <a href="#cups_dest_t"><code>cups_dest_t</code></a> structure which
-includes the name (<code>name</code>), instance (<code>instance</code> -
-a way of selecting certain saved options/settings), and the options and
-attributes associated with that destination (<code>num_options</code> and
-<code>options</code>). Destinations are created using the
-<a href="#cupsGetDests"><code>cupsGetDests</code></a> function and freed
-using the <a href='#cupsFreeDests'><code>cupsFreeDests</code></a> function.
-The <a href='#cupsGetDest'><code>cupsGetDest</code></a> function finds a
-specific destination for printing:</p>
-
-<pre class='example'>
-#include &lt;cups/cups.h&gt;
-
-<a href='#cups_dest_t'>cups_dest_t</a> *dests;
-int num_dests = <a href='#cupsGetDests'>cupsGetDests</a>(&amp;dests);
-<a href='#cups_dest_t'>cups_dest_t</a> *dest = <a href='#cupsGetDest'>cupsGetDest</a>("name", NULL, num_dests, dests);
-
-/* do something with dest */
-
-<a href='#cupsFreeDests'>cupsFreeDests</a>(num_dests, dests);
-</pre>
-
-<p>Passing <code>NULL</code> to
-<a href='#cupsGetDest'><code>cupsGetDest</code></a> for the destination name
-will return the default destination. Similarly, passing a <code>NULL</code>
-instance will return the default instance for that destination.</p>
-
-<div class='table'><table summary='Table 1: Printer Attributes' width='80%'>
-<caption>Table 1: <a name='TABLE1'>Printer Attributes</a></caption>
-<thead>
-<tr>
- <th>Attribute Name</th>
- <th>Description</th>
-</tr>
-</thead>
-<tbody>
-<tr>
- <td>"auth-info-required"</td>
- <td>The type of authentication required for printing to this
- destination: "none", "username,password", "domain,username,password",
- or "negotiate" (Kerberos)</td>
-</tr>
-<tr>
- <td>"printer-info"</td>
- <td>The human-readable description of the destination such as "My
- Laser Printer".</td>
-</tr>
-<tr>
- <td>"printer-is-accepting-jobs"</td>
- <td>"true" if the destination is accepting new jobs, "false" if
- not.</td>
-</tr>
-<tr>
- <td>"printer-is-shared"</td>
- <td>"true" if the destination is being shared with other computers,
- "false" if not.</td>
-</tr>
-<tr>
- <td>"printer-location"</td>
- <td>The human-readable location of the destination such as "Lab 4".</td>
-</tr>
-<tr>
- <td>"printer-make-and-model"</td>
- <td>The human-readable make and model of the destination such as "HP
- LaserJet 4000 Series".</td>
-</tr>
-<tr>
- <td>"printer-state"</td>
- <td>"3" if the destination is idle, "4" if the destination is printing
- a job, and "5" if the destination is stopped.</td>
-</tr>
-<tr>
- <td>"printer-state-change-time"</td>
- <td>The UNIX time when the destination entered the current state.</td>
-</tr>
-<tr>
- <td>"printer-state-reasons"</td>
- <td>Additional comma-delimited state keywords for the destination
- such as "media-tray-empty-error" and "toner-low-warning".</td>
-</tr>
-<tr>
- <td>"printer-type"</td>
- <td>The <a href='#cups_printer_t'><code>cups_printer_t</code></a>
- value associated with the destination.</td>
-</tr>
-</tbody>
-</table></div>
-
-<h3><a name='OPTIONS'>Options</a></h3>
-
-<p>Options are stored in arrays of
-<a href='#cups_option_t'><code>cups_option_t</code></a> structures. Each
-option has a name (<code>name</code>) and value (<code>value</code>)
-associated with it. The <a href='#cups_dest_t'><code>cups_dest_t</code></a>
-<code>num_options</code> and <code>options</code> members contain the
-default options for a particular destination, along with several informational
-attributes about the destination as shown in <a href='#TABLE1'>Table 1</a>.
-The <a href='#cupsGetOption'><code>cupsGetOption</code></a> function gets
-the value for the named option. For example, the following code lists the
-available destinations and their human-readable descriptions:</p>
-
-<pre class='example'>
-#include &lt;cups/cups.h&gt;
-
-<a href='#cups_dest_t'>cups_dest_t</a> *dests;
-int num_dests = <a href='#cupsGetDests'>cupsGetDests</a>(&amp;dests);
-<a href='#cups_dest_t'>cups_dest_t</a> *dest;
-int i;
-const char *value;
-
-for (i = num_dests, dest = dests; i > 0; i --, dest ++)
- if (dest->instance == NULL)
- {
- value = <a href='#cupsGetOption'>cupsGetOption</a>("printer-info", dest->num_options, dest->options);
- printf("%s (%s)\n", dest->name, value ? value : "no description");
- }
-
-<a href='#cupsFreeDests'>cupsFreeDests</a>(num_dests, dests);
-</pre>
-
-<p>You can create your own option arrays using the
-<a href='#cupsAddOption'><code>cupsAddOption</code></a> function, which
-adds a single named option to an array:</p>
-
-<pre class='example'>
-#include &lt;cups/cups.h&gt;
-
-int num_options = 0;
-<a href='#cups_option_t'>cups_option_t</a> *options = NULL;
-
-/* The returned num_options value is updated as needed */
-num_options = <a href='#cupsAddOption'>cupsAddOption</a>("first", "value", num_options, &amp;options);
-
-/* This adds a second option value */
-num_options = <a href='#cupsAddOption'>cupsAddOption</a>("second", "value", num_options, &amp;options);
-
-/* This replaces the first option we added */
-num_options = <a href='#cupsAddOption'>cupsAddOption</a>("first", "new value", num_options, &amp;options);
-</pre>
-
-<p>Use a <code>for</code> loop to copy the options from a destination:</p>
-
-<pre class='example'>
-#include &lt;cups/cups.h&gt;
-
-int i;
-int num_options = 0;
-<a href='#cups_option_t'>cups_option_t</a> *options = NULL;
-<a href='#cups_dest_t'>cups_dest_t</a> *dest;
-
-for (i = 0; i &lt; dest->num_options; i ++)
- num_options = <a href='#cupsAddOption'>cupsAddOption</a>(dest->options[i].name, dest->options[i].value,
- num_options, &amp;options);
-</pre>
-
-<p>Use the <a href='#cupsFreeOptions'><code>cupsFreeOptions</code></a>
-function to free the options array when you are done using it:</p>
-
-<pre class='example'>
-<a href='#cupsFreeOptions'>cupsFreeOptions</a>(num_options, options);
-</pre>
-
-<h3><a name='PRINT_JOBS'>Print Jobs</a></h3>
-
-<p>Print jobs are identified by a locally-unique job ID number from 1 to
-2<sup>31</sup>-1 and have options and one or more files for printing to a
-single destination. The <a href='#cupsPrintFile'><code>cupsPrintFile</code></a>
-function creates a new job with one file. The following code prints the CUPS
-test page file:</p>
-
-<pre class='example'>
-#include &lt;cups/cups.h&gt;
-
-<a href='#cups_dest_t'>cups_dest_t</a> *dest;
-int num_options;
-<a href='#cups_option_t'>cups_option_t</a> *options;
-int job_id;
-
-/* Print a single file */
-job_id = <a href='#cupsPrintFile'>cupsPrintFile</a>(dest->name, "/usr/share/cups/data/testprint.ps",
- "Test Print", num_options, options);
-</pre>
-
-<p>The <a href='#cupsPrintFiles'><code>cupsPrintFiles</code></a> function
-creates a job with multiple files. The files are provided in a
-<code>char *</code> array:</p>
-
-<pre class='example'>
-#include &lt;cups/cups.h&gt;
-
-<a href='#cups_dest_t'>cups_dest_t</a> *dest;
-int num_options;
-<a href='#cups_option_t'>cups_option_t</a> *options;
-int job_id;
-char *files[3] = { "file1.pdf", "file2.pdf", "file3.pdf" };
-
-/* Print three files */
-job_id = <a href='#cupsPrintFiles'>cupsPrintFiles</a>(dest->name, 3, files, "Test Print", num_options, options);
-</pre>
-
-<p>Finally, the <a href='#cupsCreateJob'><code>cupsCreateJob</code></a>
-function creates a new job with no files in it. Files are added using the
-<a href='#cupsStartDocument'><code>cupsStartDocument</code></a>,
-<a href='api-httpipp.html#cupsWriteRequestData'><code>cupsWriteRequestData</code></a>,
-and <a href='#cupsFinishDocument'><code>cupsFinishDocument</code></a> functions.
-The following example creates a job with 10 text files for printing:</p>
-
-<pre class='example'>
-#include &lt;cups/cups.h&gt;
-
-<a href='#cups_dest_t'>cups_dest_t</a> *dest;
-int num_options;
-<a href='#cups_option_t'>cups_option_t</a> *options;
-int job_id;
-int i;
-char buffer[1024];
-
-/* Create the job */
-job_id = <a href='#cupsCreateJob'>cupsCreateJob</a>(CUPS_HTTP_DEFAULT, dest->name, "10 Text Files",
- num_options, options);
-
-/* If the job is created, add 10 files */
-if (job_id > 0)
-{
- for (i = 1; i &lt;= 10; i ++)
- {
- snprintf(buffer, sizeof(buffer), "file%d.txt", i);
-
- <a href='#cupsStartDocument'>cupsStartDocument</a>(CUPS_HTTP_DEFAULT, dest->name, job_id, buffer,
- CUPS_FORMAT_TEXT, i == 10);
-
- snprintf(buffer, sizeof(buffer),
- "File %d\n"
- "\n"
- "One fish,\n"
- "Two fish,\n
- "Red fish,\n
- "Blue fish\n", i);
-
- /* cupsWriteRequestData can be called as many times as needed */
- <a href='#cupsWriteRequestData'>cupsWriteRequestData</a>(CUPS_HTTP_DEFAULT, buffer, strlen(buffer));
-
- <a href='#cupsFinishDocument'>cupsFinishDocument</a>(CUPS_HTTP_DEFAULT, dest->name);
- }
-}
-</pre>
-
-<p>Once you have created a job, you can monitor its status using the
-<a href='#cupsGetJobs'><code>cupsGetJobs</code></a> function, which returns
-an array of <a href='#cups_job_t'><code>cups_job_t</code></a> structures.
-Each contains the job ID (<code>id</code>), destination name
-(<code>dest</code>), title (<code>title</code>), and other information
-associated with the job. The job array is freed using the
-<a href='#cupsFreeJobs'><code>cupsFreeJobs</code></a> function. The following
-example monitors a specific job ID, showing the current job state once every
-5 seconds until the job is completed:</p>
-
-<pre class='example'>
-#include &lt;cups/cups.h&gt;
-
-<a href='#cups_dest_t'>cups_dest_t</a> *dest;
-int job_id;
-int num_jobs;
-<a href='#cups_job_t'>cups_job_t</a> *jobs;
-int i;
-ipp_jstate_t job_state = IPP_JOB_PENDING;
-
-while (job_state &lt; IPP_JOB_STOPPED)
-{
- /* Get my jobs (1) with any state (-1) */
- num_jobs = <a href='#cupsGetJobs'>cupsGetJobs</a>(&amp;jobs, dest->name, 1, -1);
-
- /* Loop to find my job */
- job_state = IPP_JOB_COMPLETED;
-
- for (i = 0; i &lt; num_jobs; i ++)
- if (jobs[i].id == job_id)
- {
- job_state = jobs[i].state;
- break;
- }
-
- /* Free the job array */
- <a href='#cupsFreeJobs'>cupsFreeJobs</a>(num_jobs, jobs);
-
- /* Show the current state */
- switch (job_state)
- {
- case IPP_JOB_PENDING :
- printf("Job %d is pending.\n", job_id);
- break;
- case IPP_JOB_HELD :
- printf("Job %d is held.\n", job_id);
- break;
- case IPP_JOB_PROCESSING :
- printf("Job %d is processing.\n", job_id);
- break;
- case IPP_JOB_STOPPED :
- printf("Job %d is stopped.\n", job_id);
- break;
- case IPP_JOB_CANCELED :
- printf("Job %d is canceled.\n", job_id);
- break;
- case IPP_JOB_ABORTED :
- printf("Job %d is aborted.\n", job_id);
- break;
- case IPP_JOB_COMPLETED :
- printf("Job %d is completed.\n", job_id);
- break;
- }
-
- /* Sleep if the job is not finished */
- if (job_state &lt; IPP_JOB_STOPPED)
- sleep(5);
-}
-</pre>
-
-<p>To cancel a job, use the
-<a href='#cupsCancelJob'><code>cupsCancelJob</code></a> function with the
-job ID:</p>
-
-<pre class='example'>
-#include &lt;cups/cups.h&gt;
-
-<a href='#cups_dest_t'>cups_dest_t</a> *dest;
-int job_id;
-
-<a href='#cupsCancelJob'>cupsCancelJob</a>(dest->name, job_id);
-</pre>
-
-<h3><a name='ERROR_HANDLING'>Error Handling</a></h3>
-
-<p>If any of the CUPS API printing functions returns an error, the reason for
-that error can be found by calling the
-<a href='#cupsLastError'><code>cupsLastError</code></a> and
-<a href='#cupsLastErrorString'><code>cupsLastErrorString</code></a> functions.
-<a href='#cupsLastError'><code>cupsLastError</code></a> returns the last IPP
-error code
-(<a href='api-httpipp.html#ipp_status_t'><code>ipp_status_t</code></a>)
-that was encountered, while
-<a href='#cupsLastErrorString'><code>cupsLastErrorString</code></a> returns
-a (localized) human-readable string that can be shown to the user. For example,
-if any of the job creation functions returns a job ID of 0, you can use
-<a href='#cupsLastErrorString'><code>cupsLastErrorString</code></a> to show
-the reason why the job could not be created:</p>
-
-<pre class='example'>
-#include &lt;cups/cups.h&gt;
-
-int job_id;
-
-if (job_id == 0)
- puts(cupsLastErrorString());
-</pre>
-
-<h3><a name='PASSWORDS_AND_AUTHENTICATION'>Passwords and Authentication</a></h3>
-
-<p>CUPS supports authentication of any request, including submission of print
-jobs. The default mechanism for getting the username and password is to use the
-login user and a password from the console.</p>
-
-<p>To support other types of applications, in particular Graphical User
-Interfaces ("GUIs"), the CUPS API provides functions to set the default
-username and to register a callback function that returns a password string.</p>
-
-<p>The <a href="#cupsSetPasswordCB"><code>cupsSetPasswordCB</code></a>
-function is used to set a password callback in your program. Only one
-function can be used at any time.</p>
-
-<p>The <a href="#cupsSetUser"><code>cupsSetUser</code></a> function sets the
-current username for authentication. This function can be called by your
-password callback function to change the current username as needed.</p>
-
-<p>The following example shows a simple password callback that gets a
-username and password from the user:</p>
-
-<pre class='example'>
-#include &lt;cups/cups.h&gt;
-
-const char *
-my_password_cb(const char *prompt)
-{
- char user[65];
-
-
- puts(prompt);
-
- /* Get a username from the user */
- printf("Username: ");
- if (fgets(user, sizeof(user), stdin) == NULL)
- return (NULL);
-
- /* Strip the newline from the string and set the user */
- user[strlen(user) - 1] = '\0';
-
- <a href='#cupsSetUser'>cupsSetUser</a>(user);
-
- /* Use getpass() to ask for the password... */
- return (getpass("Password: "));
-}
-
-<a href='#cupsSetPasswordCB'>cupsSetPasswordCB</a>(my_password_cb);
-</pre>
-
-<p>Similarly, a GUI could display the prompt string in a window with input
-fields for the username and password. The username should default to the
-string returned by the <a href="#cupsUser"><code>cupsUser</code></a>
-function.</p>
diff --git a/cups/api-filedir.header b/cups/api-filedir.header
deleted file mode 100644
index 87744eed..00000000
--- a/cups/api-filedir.header
+++ /dev/null
@@ -1,34 +0,0 @@
-<!--
- File and Directory API header for CUPS.
-
- Copyright 2008-2011 by Apple Inc.
-
- 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/".
--->
-
-<h1 class='title'>File and Directory APIs</h1>
-
-<div class='summary'><table summary='General Information'>
-<thead>
-<tr>
- <th>Headers</th>
- <th>cups/file.h<br>
- cups/dir.h</th>
-</tr>
-</thead>
-<tbody>
-<tr>
- <th>Library</th>
- <td>-lcups</td>
-</tr>
-<tr>
- <th>See Also</th>
- <td>Programming: <a href='api-overview.html' target='_top'>Introduction to CUPS Programming</a><br>
- Programming: <a href='api-cups.html' target='_top'>CUPS API</a></td>
-</tr>
-</tbody>
-</table></div>
diff --git a/cups/api-filedir.shtml b/cups/api-filedir.shtml
deleted file mode 100644
index 8fdbee64..00000000
--- a/cups/api-filedir.shtml
+++ /dev/null
@@ -1,29 +0,0 @@
-<!--
- File and directory API introduction for CUPS.
-
- 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
- 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/".
--->
-
-<h2 class='title'><a name="OVERVIEW">Overview</a></h2>
-
-<p>The CUPS file and directory APIs provide portable interfaces
-for manipulating files and listing files and directories. Unlike
-stdio <code>FILE</code> streams, the <code>cupsFile</code> functions
-allow you to open more than 256 files at any given time. They
-also manage the platform-specific details of locking, large file
-support, line endings (CR, LF, or CR LF), and reading and writing
-files using Flate ("gzip") compression. Finally, you can also
-connect, read from, and write to network connections using the
-<code>cupsFile</code> functions.</p>
-
-<p>The <code>cupsDir</code> functions manage the platform-specific
-details of directory access/listing and provide a convenient way
-to get both a list of files and the information (permissions,
-size, timestamp, etc.) for each of those files.</p>
diff --git a/cups/api-httpipp.header b/cups/api-httpipp.header
deleted file mode 100644
index cbede8f6..00000000
--- a/cups/api-httpipp.header
+++ /dev/null
@@ -1,37 +0,0 @@
-<!--
- HTTP and IPP API header for CUPS.
-
- Copyright 2007-2016 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/".
--->
-
-<h1 class='title'>HTTP and IPP APIs</h1>
-
-<div class='summary'><table summary='General Information'>
-<thead>
-<tr>
- <th>Headers</th>
- <th>cups/cups.h<br>
- cups/http.h<br>
- cups/ipp.h</th>
-</tr>
-</thead>
-<tbody>
-<tr>
- <th>Library</th>
- <td>-lcups</td>
-</tr>
-<tr>
- <th>See Also</th>
- <td>Programming: <a href='api-overview.html'>Introduction to CUPS Programming</a><br>
- Programming: <a href='api-cups.html'>CUPS API</a><br>
- References: <a href='spec-ipp.html'>CUPS Implementation of IPP</a></td>
-</tr>
-</tbody>
-</table></div>
diff --git a/cups/api-httpipp.shtml b/cups/api-httpipp.shtml
deleted file mode 100644
index 33bf5ad3..00000000
--- a/cups/api-httpipp.shtml
+++ /dev/null
@@ -1,315 +0,0 @@
-<!--
- HTTP and IPP API introduction for CUPS.
-
- Copyright 2007-2012 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/".
--->
-
-<h2 class='title'><a name='OVERVIEW'>Overview</a></h2>
-
-<p>The CUPS HTTP and IPP APIs provide low-level access to the HTTP and IPP
-protocols and CUPS scheduler. They are typically used by monitoring and
-administration programs to perform specific functions not supported by the
-high-level CUPS API functions.</p>
-
-<p>The HTTP APIs use an opaque structure called
-<a href='#http_t'><code>http_t</code></a> to manage connections to
-a particular HTTP or IPP server. The
-<a href='#httpConnectEncrypt'><code>httpConnectEncrypt</code></a> function is
-used to create an instance of this structure for a particular server.
-The constant <code>CUPS_HTTP_DEFAULT</code> can be used with all of the
-<code>cups</code> functions to refer to the default CUPS server - the functions
-create a per-thread <a href='#http_t'><code>http_t</code></a> as needed.</p>
-
-<p>The IPP APIs use two opaque structures for requests (messages sent to the CUPS scheduler) and responses (messages sent back to your application from the scheduler). The <a href='#ipp_t'><code>ipp_t</code></a> type holds a complete request or response and is allocated using the <a href='#ippNew'><code>ippNew</code></a> or <a href='#ippNewRequest'><code>ippNewRequest</code></a> functions and freed using the <a href='#ippDelete'><code>ippDelete</code></a> function.</p>
-
-<p>The second opaque structure is called <a href='#ipp_attribute_t'><code>ipp_attribute_t</code></a> and holds a single IPP attribute which consists of a group tag (<a href='#ippGetGroupTag'><code>ippGetGroupTag</code></a>), a value type tag (<a href='#ippGetValueTag'><code>ippGetValueTag</code></a>), the attribute name (<a href='#ippGetName'><code>ippGetName</code></a>), and 1 or more values (<a href='#ippGetCount'><code>ippGetCount</code></a>, <a href='#ippGetBoolean'><code>ippGetBoolean</code></a>, <a href='#ippGetCollection'><code>ippGetCollection</code></a>, <a href='#ippGetDate'><code>ippGetDate</code></a>, <a href='#ippGetInteger'><code>ippGetInteger</code></a>, <a href='#ippGetRange'><code>ippGetRange</code></a>, <a href='#ippGetResolution'><code>ippGetResolution</code></a>, and <a href='#ippGetString'><code>ippGetString</code></a>). Attributes are added to an <a href='#ipp_t'><code>ipp_t</code></a> pointer using one of the <code>ippAdd</code> functions. For example, use <a href='#ippAddString'><code>ippAddString</code></a> to add the "printer-uri" and "requesting-user-name" string attributes to a request:</p>
-
-<pre class='example'>
-<a href='#ipp_t'>ipp_t</a> *request = <a href='#ippNewRequest'>ippNewRequest</a>(IPP_GET_JOBS);
-
-<a href='#ippAddString'>ippAddString</a>(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
- NULL, "ipp://localhost/printers/");
-<a href='#ippAddString'>ippAddString</a>(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
- NULL, cupsUser());
-</pre>
-
-<p>Once you have created an IPP request, use the <code>cups</code> functions to send the request to and read the response from the server. For example, the <a href='#cupsDoRequest'><code>cupsDoRequest</code></a> function can be used for simple query operations that do not involve files:</p>
-
-<pre class='example'>
-#include &lt;cups/cups.h&gt;
-
-
-<a href='#ipp_t'>ipp_t</a> *<a name='get_jobs'>get_jobs</a>(void)
-{
- <a href='#ipp_t'>ipp_t</a> *request = <a href='#ippNewRequest'>ippNewRequest</a>(IPP_GET_JOBS);
-
- <a href='#ippAddString'>ippAddString</a>(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
- NULL, "ipp://localhost/printers/");
- <a href='#ippAddString'>ippAddString</a>(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
- NULL, cupsUser());
-
- return (<a href='#cupsDoRequest'>cupsDoRequest</a>(CUPS_HTTP_DEFAULT, request, "/"));
-}
-</pre>
-
-<p>The <a href='#cupsDoRequest'><code>cupsDoRequest</code></a> function frees the request and returns an IPP response or <code>NULL</code> pointer if the request could not be sent to the server. Once you have a response from the server, you can either use the <a href='#ippFindAttribute'><code>ippFindAttribute</code></a> and <a href='#ippFindNextAttribute'><code>ippFindNextAttribute</code></a> functions to find specific attributes, for example:</p>
-
-<pre class='example'>
-<a href='#ipp_t'>ipp_t</a> *response;
-<a href='#ipp_attribute_t'>ipp_attribute_t</a> *attr;
-
-attr = <a href='#ippFindAttribute'>ippFindAttribute</a>(response, "printer-state", IPP_TAG_ENUM);
-</pre>
-
-<p>You can also walk the list of attributes with a simple <code>for</code> loop like this:</p>
-
-<pre class='example'>
-<a href='#ipp_t'>ipp_t</a> *response;
-<a href='#ipp_attribute_t'>ipp_attribute_t</a> *attr;
-
-for (attr = <a href='#ippFirstAttribute'>ippFirstAttribute</a>(response); attr != NULL; attr = <a href='#ippNextAttribute'>ippNextAttribute</a>(response))
- if (ippGetName(attr) == NULL)
- puts("--SEPARATOR--");
- else
- puts(ippGetName(attr));
-</pre>
-
-<p>The <code>for</code> loop approach is normally used when collecting attributes for multiple objects (jobs, printers, etc.) in a response. Attributes with <code>NULL</code> names indicate a separator between the attributes of each object. For example, the following code will list the jobs returned from our previous <a href='#get_jobs'><code>get_jobs</code></a> example code:</p>
-
-<pre class='example'>
-<a href='#ipp_t'>ipp_t</a> *response = <a href='#get_jobs'>get_jobs</a>();
-
-if (response != NULL)
-{
- <a href='#ipp_attribute_t'>ipp_attribute_t</a> *attr;
- const char *attrname;
- int job_id = 0;
- const char *job_name = NULL;
- const char *job_originating_user_name = NULL;
-
- puts("Job ID Owner Title");
- puts("------ ---------------- ---------------------------------");
-
- for (attr = <a href='#ippFirstAttribute'>ippFirstAttribute</a>(response); attr != NULL; attr = <a href='#ippNextAttribute'>ippNextAttribute</a>(response))
- {
- /* Attributes without names are separators between jobs */
- attrname = ippGetName(attr);
- if (attrname == NULL)
- {
- if (job_id > 0)
- {
- if (job_name == NULL)
- job_name = "(withheld)";
-
- if (job_originating_user_name == NULL)
- job_originating_user_name = "(withheld)";
-
- printf("%5d %-16s %s\n", job_id, job_originating_user_name, job_name);
- }
-
- job_id = 0;
- job_name = NULL;
- job_originating_user_name = NULL;
- continue;
- }
- else if (!strcmp(attrname, "job-id") &amp;&amp; ippGetValueTag(attr) == IPP_TAG_INTEGER)
- job_id = ippGetInteger(attr, 0);
- else if (!strcmp(attrname, "job-name") &amp;&amp; ippGetValueTag(attr) == IPP_TAG_NAME)
- job_name = ippGetString(attr, 0, NULL);
- else if (!strcmp(attrname, "job-originating-user-name") &amp;&amp;
- ippGetValueTag(attr) == IPP_TAG_NAME)
- job_originating_user_name = ippGetString(attr, 0, NULL);
- }
-
- if (job_id > 0)
- {
- if (job_name == NULL)
- job_name = "(withheld)";
-
- if (job_originating_user_name == NULL)
- job_originating_user_name = "(withheld)";
-
- printf("%5d %-16s %s\n", job_id, job_originating_user_name, job_name);
- }
-}
-</pre>
-
-<h3><a name='CREATING_URI_STRINGS'>Creating URI Strings</a></h3>
-
-<p>To ensure proper encoding, the
-<a href='#httpAssembleURIf'><code>httpAssembleURIf</code></a> function must be
-used to format a "printer-uri" string for all printer-based requests:</p>
-
-<pre class='example'>
-const char *name = "Foo";
-char uri[1024];
-<a href='#ipp_t'>ipp_t</a> *request;
-
-<a href='#httpAssembleURIf'>httpAssembleURIf</a>(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL, cupsServer(),
- ippPort(), "/printers/%s", name);
-<a href='#ippAddString'>ippAddString</a>(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, uri);
-</pre>
-
-<h3><a name='SENDING_REQUESTS_WITH_FILES'>Sending Requests with Files</a></h3>
-
-<p>The <a href='#cupsDoFileRequest'><code>cupsDoFileRequest</code></a> and
-<a href='#cupsDoIORequest'><code>cupsDoIORequest</code></a> functions are
-used for requests involving files. The
-<a href='#cupsDoFileRequest'><code>cupsDoFileRequest</code></a> function
-attaches the named file to a request and is typically used when sending a print
-file or changing a printer's PPD file:</p>
-
-<pre class='example'>
-const char *filename = "/usr/share/cups/data/testprint.ps";
-const char *name = "Foo";
-char uri[1024];
-char resource[1024];
-<a href='#ipp_t'>ipp_t</a> *request = <a href='#ippNewRequest'>ippNewRequest</a>(IPP_PRINT_JOB);
-<a href='#ipp_t'>ipp_t</a> *response;
-
-/* Use httpAssembleURIf for the printer-uri string */
-<a href='#httpAssembleURIf'>httpAssembleURIf</a>(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL, cupsServer(),
- ippPort(), "/printers/%s", name);
-<a href='#ippAddString'>ippAddString</a>(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, uri);
-<a href='#ippAddString'>ippAddString</a>(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
- NULL, cupsUser());
-<a href='#ippAddString'>ippAddString</a>(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "job-name",
- NULL, "testprint.ps");
-
-/* Use snprintf for the resource path */
-snprintf(resource, sizeof(resource), "/printers/%s", name);
-
-response = <a href='#cupsDoFileRequest'>cupsDoFileRequest</a>(CUPS_HTTP_DEFAULT, request, resource, filename);
-</pre>
-
-<p>The <a href='#cupsDoIORequest'><code>cupsDoIORequest</code></a> function
-optionally attaches a file to the request and optionally saves a file in the
-response from the server. It is used when using a pipe for the request
-attachment or when using a request that returns a file, currently only
-<code>CUPS_GET_DOCUMENT</code> and <code>CUPS_GET_PPD</code>. For example,
-the following code will download the PPD file for the sample HP LaserJet
-printer driver:</p>
-
-<pre class='example'>
-char tempfile[1024];
-int tempfd;
-<a href='#ipp_t'>ipp_t</a> *request = <a href='#ippNewRequest'>ippNewRequest</a>(CUPS_GET_PPD);
-<a href='#ipp_t'>ipp_t</a> *response;
-
-<a href='#ippAddString'>ippAddString</a>(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "ppd-name",
- NULL, "laserjet.ppd");
-
-tempfd = cupsTempFd(tempfile, sizeof(tempfile));
-
-response = <a href='#cupsDoIORequest'>cupsDoIORequest</a>(CUPS_HTTP_DEFAULT, request, "/", -1, tempfd);
-</pre>
-
-<p>The example passes <code>-1</code> for the input file descriptor to specify
-that no file is to be attached to the request. The PPD file attached to the
-response is written to the temporary file descriptor we created using the
-<code>cupsTempFd</code> function.</p>
-
-<h3><a name='ASYNCHRONOUS_REQUEST_PROCESSING'>Asynchronous Request Processing</a></h3>
-
-<p>The <a href='#cupsSendRequest'><code>cupsSendRequest</code></a> and
-<a href='#cupsGetResponse'><code>cupsGetResponse</code></a> support
-asynchronous communications with the server. Unlike the other request
-functions, the IPP request is not automatically freed, so remember to
-free your request with the <a href='#ippDelete'><code>ippDelete</code></a>
-function.</p>
-
-<p>File data is attached to the request using the
-<a href='#cupsWriteRequestData'><code>cupsWriteRequestData</code></a>
-function, while file data returned from the server is read using the
-<a href='#cupsReadResponseData'><code>cupsReadResponseData</code></a>
-function. We can rewrite the previous <code>CUPS_GET_PPD</code> example
-to use the asynchronous functions quite easily:</p>
-
-<pre class='example'>
-char tempfile[1024];
-int tempfd;
-<a href='#ipp_t'>ipp_t</a> *request = <a href='#ippNewRequest'>ippNewRequest</a>(CUPS_GET_PPD);
-<a href='#ipp_t'>ipp_t</a> *response;
-
-<a href='#ippAddString'>ippAddString</a>(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "ppd-name",
- NULL, "laserjet.ppd");
-
-tempfd = cupsTempFd(tempfile, sizeof(tempfile));
-
-if (<a href='#cupsSendRequest'>cupsSendRequest</a>(CUPS_HTTP_DEFAULT, request, "/") == HTTP_CONTINUE)
-{
- response = <a href='#cupsGetResponse'>cupsGetResponse</a>(CUPS_HTTP_DEFAULT, "/");
-
- if (response != NULL)
- {
- ssize_t bytes;
- char buffer[8192];
-
- while ((bytes = <a href='#cupsReadResponseData'>cupsReadResponseData</a>(CUPS_HTTP_DEFAULT, buffer, sizeof(buffer))) > 0)
- write(tempfd, buffer, bytes);
- }
-}
-
-/* Free the request! */
-<a href='#ippDelete'>ippDelete</a>(request);
-</pre>
-
-<p>The <a href='#cupsSendRequest'><code>cupsSendRequest</code></a> function
-returns the initial HTTP request status, typically either
-<code>HTTP_CONTINUE</code> or <code>HTTP_UNAUTHORIZED</code>. The latter status
-is returned when the request requires authentication of some sort. The
-<a href='#cupsDoAuthentication'><code>cupsDoAuthentication</code></a> function
-must be called when your see <code>HTTP_UNAUTHORIZED</code> and the request
-re-sent. We can add authentication support to our example code by using a
-<code>do ... while</code> loop:</p>
-
-<pre class='example'>
-char tempfile[1024];
-int tempfd;
-<a href='#ipp_t'>ipp_t</a> *request = <a href='#ippNewRequest'>ippNewRequest</a>(CUPS_GET_PPD);
-<a href='#ipp_t'>ipp_t</a> *response;
-http_status_t status;
-
-<a href='#ippAddString'>ippAddString</a>(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "ppd-name",
- NULL, "laserjet.ppd");
-
-tempfd = cupsTempFd(tempfile, sizeof(tempfile));
-
-/* Loop for authentication */
-do
-{
- status = <a href='#cupsSendRequest'>cupsSendRequest</a>(CUPS_HTTP_DEFAULT, request, "/");
-
- if (status == HTTP_UNAUTHORIZED)
- {
- /* Try to authenticate, break out of the loop if that fails */
- if (<a href='#cupsDoAuthentication'>cupsDoAuthentication</a>(CUPS_HTTP_DEFAULT, "POST", "/"))
- break;
- }
-}
-while (status != HTTP_CONTINUE &amp;&amp; status != HTTP_UNAUTHORIZED);
-
-if (status == HTTP_CONTINUE)
-{
- response = <a href='#cupsGetResponse'>cupsGetResponse</a>(CUPS_HTTP_DEFAULT, "/");
-
- if (response != NULL)
- {
- ssize_t bytes;
- char buffer[8192];
-
- while ((bytes = <a href='#cupsReadResponseData'>cupsReadResponseData</a>(CUPS_HTTP_DEFAULT, buffer, sizeof(buffer))) > 0)
- write(tempfd, buffer, bytes);
- }
-}
-
-/* Free the request! */
-<a href='#ippDelete'>ippDelete</a>(request);
-</pre>
diff --git a/cups/auth.c b/cups/auth.c
index 8348a2cc..c051c86b 100644
--- a/cups/auth.c
+++ b/cups/auth.c
@@ -54,7 +54,7 @@ extern const char *cssmErrorString(int error);
# 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
+typedef struct gss_auth_identity /* @private@ */
{
uint32_t type;
uint32_t flags;
diff --git a/cups/cups-private.h b/cups/cups-private.h
index 264fd01c..6fd66a9c 100644
--- a/cups/cups-private.h
+++ b/cups/cups-private.h
@@ -1,7 +1,7 @@
/*
* Private definitions for CUPS.
*
- * Copyright 2007-2015 by Apple Inc.
+ * Copyright 2007-2017 by Apple Inc.
* Copyright 1997-2007 by Easy Software Products, all rights reserved.
*
* These coded instructions, statements, and computer programs are the
@@ -105,7 +105,7 @@ typedef struct _cups_globals_s /**** CUPS global state data ****/
int need_res_init; /* Need to reinitialize resolver? */
/* ipp.c */
- ipp_uchar_t ipp_date[11]; /* RFC-1903 date/time data */
+ ipp_uchar_t ipp_date[11]; /* RFC-2579 date/time data */
_cups_buffer_t *cups_buffers; /* Buffer list */
/* ipp-support.c */
diff --git a/cups/cups.h b/cups/cups.h
index 3205dd82..8f5c818f 100644
--- a/cups/cups.h
+++ b/cups/cups.h
@@ -47,10 +47,10 @@ extern "C" {
* Constants...
*/
-# define CUPS_VERSION 2.0203
+# define CUPS_VERSION 2.0206
# define CUPS_VERSION_MAJOR 2
# define CUPS_VERSION_MINOR 2
-# define CUPS_VERSION_PATCH 3
+# define CUPS_VERSION_PATCH 6
# define CUPS_BC_FD 3
/* Back-channel file descriptor for
@@ -78,7 +78,7 @@ extern "C" {
# define CUPS_DEST_FLAGS_NONE 0x00
/* No flags are set */
# define CUPS_DEST_FLAGS_UNCONNECTED 0x01
- /* There is not connection */
+ /* There is no connection */
# define CUPS_DEST_FLAGS_MORE 0x02
/* There are more destinations */
# define CUPS_DEST_FLAGS_REMOVED 0x04
@@ -92,6 +92,8 @@ extern "C" {
/* A connection is being established */
# define CUPS_DEST_FLAGS_CANCELED 0x40
/* Operation was canceled */
+# define CUPS_DEST_FLAGS_DEVICE 0x80
+ /* For @link cupsConnectDest@: Connect to device */
/* Flags for cupsGetDestMediaByName/Size */
# define CUPS_MEDIA_FLAGS_DEFAULT 0x00
@@ -207,38 +209,37 @@ enum cups_ptype_e /* Printer type/capability bit
CUPS_PRINTER_REMOTE = 0x0002, /* Remote printer or class */
CUPS_PRINTER_BW = 0x0004, /* Can do B&W printing */
CUPS_PRINTER_COLOR = 0x0008, /* Can do color printing */
- CUPS_PRINTER_DUPLEX = 0x0010, /* Can do duplexing */
+ CUPS_PRINTER_DUPLEX = 0x0010, /* Can do two-sided printing */
CUPS_PRINTER_STAPLE = 0x0020, /* Can staple output */
- CUPS_PRINTER_COPIES = 0x0040, /* Can do copies */
- CUPS_PRINTER_COLLATE = 0x0080, /* Can collage copies */
+ CUPS_PRINTER_COPIES = 0x0040, /* Can do copies in hardware */
+ CUPS_PRINTER_COLLATE = 0x0080, /* Can quickly collate copies */
CUPS_PRINTER_PUNCH = 0x0100, /* Can punch output */
CUPS_PRINTER_COVER = 0x0200, /* Can cover output */
CUPS_PRINTER_BIND = 0x0400, /* Can bind output */
CUPS_PRINTER_SORT = 0x0800, /* Can sort output */
- CUPS_PRINTER_SMALL = 0x1000, /* Can do Letter/Legal/A4 */
- 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_SMALL = 0x1000, /* Can print on Letter/Legal/A4-size media */
+ CUPS_PRINTER_MEDIUM = 0x2000, /* Can print on Tabloid/B/C/A3/A2-size media */
+ CUPS_PRINTER_LARGE = 0x4000, /* Can print on D/E/A1/A0-size media */
+ CUPS_PRINTER_VARIABLE = 0x8000, /* Can print on rolls and custom-size media */
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 */
CUPS_PRINTER_DELETE = 0x100000, /* Delete printer
- * @since CUPS 1.2/macOS 10.5@ */
+ * @deprecated@ @exclude all@ */
CUPS_PRINTER_NOT_SHARED = 0x200000, /* Printer is not shared
* @since CUPS 1.2/macOS 10.5@ */
CUPS_PRINTER_AUTHENTICATED = 0x400000,/* Printer requires authentication
* @since CUPS 1.2/macOS 10.5@ */
CUPS_PRINTER_COMMANDS = 0x800000, /* Printer supports maintenance commands
* @since CUPS 1.2/macOS 10.5@ */
- CUPS_PRINTER_DISCOVERED = 0x1000000, /* Printer was automatically discovered
- * and added @private@ */
+ CUPS_PRINTER_DISCOVERED = 0x1000000, /* Printer was discovered @since CUPS 1.2/macOS 10.5@ */
CUPS_PRINTER_SCANNER = 0x2000000, /* Scanner-only device
- * @since CUPS 1.4/macOS 10.6@ */
+ * @since CUPS 1.4/macOS 10.6@ @private@ */
CUPS_PRINTER_MFP = 0x4000000, /* Printer with scanning capabilities
- * @since CUPS 1.4/macOS 10.6@ */
- CUPS_PRINTER_3D = 0x8000000, /* Printer with 3D capabilities @private@ */
+ * @since CUPS 1.4/macOS 10.6@ @private@ */
+ CUPS_PRINTER_3D = 0x8000000, /* Printer with 3D capabilities @exclude all@ @private@ */
CUPS_PRINTER_OPTIONS = 0x6fffc /* ~(CLASS | REMOTE | IMPLICIT |
* DEFAULT | FAX | REJECTING | DELETE |
* NOT_SHARED | AUTHENTICATED |
@@ -269,7 +270,7 @@ typedef struct cups_job_s /**** Job ****/
int id; /* The job ID */
char *dest; /* Printer or class name */
char *title; /* Title/job name */
- char *user; /* User the submitted the job */
+ char *user; /* User that submitted the job */
char *format; /* Document format */
ipp_jstate_t state; /* Job state */
int size; /* Size in kilobytes */
@@ -309,11 +310,12 @@ typedef int (*cups_dest_cb_t)(void *user_data, unsigned flags,
# ifdef __BLOCKS__
typedef int (^cups_dest_block_t)(unsigned flags, cups_dest_t *dest);
/* Destination enumeration block
- * @since CUPS 1.6/macOS 10.8@ */
+ * @since CUPS 1.6/macOS 10.8@
+ * @exclude all@ */
# endif /* __BLOCKS__ */
typedef const char *(*cups_password_cb_t)(const char *prompt);
- /* Password callback */
+ /* Password callback @exclude all@ */
typedef const char *(*cups_password_cb2_t)(const char *prompt, http_t *http,
const char *method,
@@ -340,11 +342,11 @@ extern ipp_t *cupsDoRequest(http_t *http, ipp_t *request,
const char *resource);
extern http_encryption_t cupsEncryption(void);
extern void cupsFreeJobs(int num_jobs, cups_job_t *jobs);
-extern int cupsGetClasses(char ***classes) _CUPS_DEPRECATED_MSG("Use cupsGetDests instead.");
+extern int cupsGetClasses(char ***classes) _CUPS_DEPRECATED_MSG("Use cupsEnumDests instead.");
extern const char *cupsGetDefault(void);
extern int cupsGetJobs(cups_job_t **jobs, const char *name,
int myjobs, int whichjobs);
-extern int cupsGetPrinters(char ***printers) _CUPS_DEPRECATED_MSG("Use cupsGetDests instead.");
+extern int cupsGetPrinters(char ***printers) _CUPS_DEPRECATED_MSG("Use cupsEnumDests instead.");
extern ipp_status_t cupsLastError(void);
extern int cupsPrintFile(const char *name, const char *filename,
const char *title, int num_options,
@@ -600,6 +602,10 @@ extern int cupsSetServerCredentials(const char *path, const char *common_name,
/* New in CUPS 2.2/macOS 10.12 */
extern ssize_t cupsHashData(const char *algorithm, const void *data, size_t datalen, unsigned char *hash, size_t hashsize) _CUPS_API_2_2;
+/* New in CUPS 2.2.4 */
+extern int cupsAddIntegerOption(const char *name, int value, int num_options, cups_option_t **options) _CUPS_API_2_2_4;
+extern int cupsGetIntegerOption(const char *name, int num_options, cups_option_t *options) _CUPS_API_2_2_4;
+
# ifdef __cplusplus
}
# endif /* __cplusplus */
diff --git a/cups/cupspm-icon.png b/cups/cupspm-icon.png
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/cups/cupspm-icon.png
diff --git a/cups/cupspm.md b/cups/cupspm.md
new file mode 100644
index 00000000..cb381ac2
--- /dev/null
+++ b/cups/cupspm.md
@@ -0,0 +1,994 @@
+---
+title: CUPS Programming Manual
+author: Michael R Sweet
+copyright: Copyright © 2007-2017 by Apple Inc. All Rights Reserved.
+version: 2.2.5
+...
+
+> Please [file issues on Github](https://github.com/apple/cups/issues) to
+> provide feedback on this document.
+
+
+# Introduction
+
+CUPS provides the "cups" library to talk to the different parts of CUPS and with
+Internet Printing Protocol (IPP) printers. The "cups" library functions are
+accessed by including the `<cups/cups.h>` header.
+
+CUPS is based on the Internet Printing Protocol ("IPP"), which allows clients
+(applications) to communicate with a server (the scheduler, printers, etc.) to
+get a list of destinations, send print jobs, and so forth. You identify which
+server you want to communicate with using a pointer to the opaque structure
+`http_t`. The `CUPS_HTTP_DEFAULT` constant can be used when you want to talk to
+the CUPS scheduler.
+
+
+## Guidelines
+
+When writing software that uses the "cups" library:
+
+- Do not use undocumented or deprecated APIs,
+- Do not rely on pre-configured printers,
+- Do not assume that printers support specific features or formats, and
+- Do not rely on implementation details (PPDs, etc.)
+
+CUPS is designed to insulate users and developers from the implementation
+details of printers and file formats. The goal is to allow an application to
+supply a print file in a standard format with the user intent ("print four
+copies, two-sided on A4 media, and staple each copy") and have the printing
+system manage the printer communication and format conversion needed.
+
+Similarly, printer and job management applications can use standard query
+operations to obtain the status information in a common, generic form and use
+standard management operations to control the state of those printers and jobs.
+
+
+## Terms Used in This Document
+
+A *Destination* is a printer or print queue that accepts print jobs. A
+*Print Job* is one or more documents that are processed by a destination
+using options supplied when creating the job. A *Document* is a file (JPEG
+image, PDF file, etc.) suitable for printing. An *Option* controls some aspect
+of printing, such as the media used. *Media* is the sheets or roll that is
+printed on. An *Attribute* is an option encoded for an Internet Printing
+Protocol (IPP) request.
+
+
+## Compiling Programs That Use the CUPS API
+
+The CUPS libraries can be used from any C, C++, or Objective C program.
+The method of compiling against the libraries varies depending on the
+operating system and installation of CUPS. The following sections show how
+to compile a simple program (shown below) in two common environments.
+
+The following simple program lists the available destinations:
+
+ #include <stdio.h>
+ #include <cups/cups.h>
+
+ int print_dest(void *user_data, unsigned flags, cups_dest_t *dest)
+ {
+ if (dest->instance)
+ printf("%s/%s\n", dest->name, dest->instance);
+ else
+ puts(dest->name);
+
+ return (1);
+ }
+
+ int main(void)
+ {
+ cupsEnumDests(CUPS_DEST_FLAGS_NONE, 1000, NULL, 0, 0, print_dest, NULL);
+
+ return (0);
+ }
+
+
+### Compiling with Xcode
+
+In Xcode, choose *New Project...* from the *File* menu (or press SHIFT+CMD+N),
+then select the *Command Line Tool* under the macOS Application project type.
+Click *Next* and enter a name for the project, for example "firstcups". Click
+*Next* and choose a project directory. The click *Next* to create the project.
+
+In the project window, click on the *Build Phases* group and expand the
+*Link Binary with Libraries* section. Click *+*, type "libcups" to show the
+library, and then double-click on `libcups.tbd`.
+
+Finally, click on the `main.c` file in the sidebar and copy the example program
+to the file. Build and run (CMD+R) to see the list of destinations.
+
+
+### Compiling with GCC
+
+From the command-line, create a file called `sample.c` using your favorite
+editor, copy the example to this file, and save. Then run the following command
+to compile it with GCC and run it:
+
+ gcc -o simple `cups-config --cflags` simple.c `cups-config --libs`
+ ./simple
+
+The `cups-config` command provides the compiler flags (`cups-config --cflags`)
+and libraries (`cups-config --libs`) needed for the local system.
+
+
+# Working with Destinations
+
+Destinations, which in CUPS represent individual printers or classes
+(collections or pools) of printers, are represented by the `cups_dest_t`
+structure which includes the name \(`name`), instance \(`instance`, saved
+options/settings), whether the destination is the default for the user
+\(`is_default`), and the options and basic information associated with that
+destination \(`num_options` and `options`).
+
+Historically destinations have been manually maintained by the administrator of
+a system or network, but CUPS also supports dynamic discovery of destinations on
+the current network.
+
+
+## Finding Available Destinations
+
+The `cupsEnumDests` function finds all of the available destinations:
+
+ int
+ cupsEnumDests(unsigned flags, int msec, int *cancel,
+ cups_ptype_t type, cups_ptype_t mask,
+ cups_dest_cb_t cb, void *user_data)
+
+The `flags` argument specifies enumeration options, which at present must be
+`CUPS_DEST_FLAGS_NONE`.
+
+The `msec` argument specifies the maximum amount of time that should be used for
+enumeration in milliseconds - interactive applications should keep this value to
+5000 or less when run on the main thread.
+
+The `cancel` argument points to an integer variable that, when set to a non-zero
+value, will cause enumeration to stop as soon as possible. It can be `NULL` if
+not needed.
+
+The `type` and `mask` arguments are bitfields that allow the caller to filter
+the destinations based on categories and/or capabilities. The destination's
+"printer-type" value is masked by the `mask` value and compared to the `type`
+value when filtering. For example, to only enumerate destinations that are
+hosted on the local system, pass `CUPS_PRINTER_LOCAL` for the `type` argument
+and `CUPS_PRINTER_DISCOVERED` for the `mask` argument. The following constants
+can be used for filtering:
+
+- `CUPS_PRINTER_CLASS`: A collection of destinations.
+- `CUPS_PRINTER_FAX`: A facsimile device.
+- `CUPS_PRINTER_LOCAL`: A local printer or class. This constant has the value 0
+ (no bits set) and is only used for the `type` argument and is paired with the
+ `CUPS_PRINTER_REMOTE` or `CUPS_PRINTER_DISCOVERED` constant passed in the
+ `mask` argument.
+- `CUPS_PRINTER_REMOTE`: A remote (shared) printer or class.
+- `CUPS_PRINTER_DISCOVERED`: An available network printer or class.
+- `CUPS_PRINTER_BW`: Can do B&W printing.
+- `CUPS_PRINTER_COLOR`: Can do color printing.
+- `CUPS_PRINTER_DUPLEX`: Can do two-sided printing.
+- `CUPS_PRINTER_STAPLE`: Can staple output.
+- `CUPS_PRINTER_COLLATE`: Can quickly collate copies.
+- `CUPS_PRINTER_PUNCH`: Can punch output.
+- `CUPS_PRINTER_COVER`: Can cover output.
+- `CUPS_PRINTER_BIND`: Can bind output.
+- `CUPS_PRINTER_SORT`: Can sort output (mailboxes, etc.)
+- `CUPS_PRINTER_SMALL`: Can print on Letter/Legal/A4-size media.
+- `CUPS_PRINTER_MEDIUM`: Can print on Tabloid/B/C/A3/A2-size media.
+- `CUPS_PRINTER_LARGE`: Can print on D/E/A1/A0-size media.
+- `CUPS_PRINTER_VARIABLE`: Can print on rolls and custom-size media.
+
+The `cb` argument specifies a function to call for every destination that is
+found:
+
+ typedef int (*cups_dest_cb_t)(void *user_data,
+ unsigned flags,
+ cups_dest_t *dest);
+
+The callback function receives a copy of the `user_data` argument along with a
+bitfield \(`flags`) and the destination that was found. The `flags` argument
+can have any of the following constant (bit) values set:
+
+- `CUPS_DEST_FLAGS_MORE`: There are more destinations coming.
+- `CUPS_DEST_FLAGS_REMOVED`: The destination has gone away and should be removed
+ from the list of destinations a user can select.
+- `CUPS_DEST_FLAGS_ERROR`: An error occurred. The reason for the error can be
+ found by calling the `cupsLastError` and/or `cupsLastErrorString` functions.
+
+The callback function returns 0 to stop enumeration or 1 to continue.
+
+> Note that the callback function will likely be called multiple times for the
+> same destination, so it is up to the caller to suppress any duplicate
+> destinations.
+
+The following example shows how to use `cupsEnumDests` to get a filtered array
+of destinations:
+
+ typedef struct
+ {
+ int num_dests;
+ cups_dest_t *dests;
+ } my_user_data_t;
+
+ int
+ my_dest_cb(my_user_data_t *user_data, unsigned flags,
+ cups_dest_t *dest)
+ {
+ if (flags & CUPS_DEST_FLAGS_REMOVED)
+ {
+ /*
+ * Remove destination from array...
+ */
+
+ user_data->num_dests =
+ cupsRemoveDest(dest->name, dest->instance,
+ user_data->num_dests,
+ &(user_data->dests));
+ }
+ else
+ {
+ /*
+ * Add destination to array...
+ */
+
+ user_data->num_dests =
+ cupsCopyDest(dest, user_data->num_dests,
+ &(user_data->dests));
+ }
+
+ return (1);
+ }
+
+ int
+ my_get_dests(cups_ptype_t type, cups_ptype_t mask,
+ cups_dest_t **dests)
+ {
+ my_user_data_t user_data = { 0, NULL };
+
+ if (!cupsEnumDests(CUPS_DEST_FLAGS_NONE, 1000, NULL, type,
+ mask, (cups_dest_cb_t)my_dest_cb,
+ &user_data))
+ {
+ /*
+ * An error occurred, free all of the destinations and
+ * return...
+ */
+
+ cupsFreeDests(user_data.num_dests, user_dasta.dests);
+
+ *dests = NULL;
+
+ return (0);
+ }
+
+ /*
+ * Return the destination array...
+ */
+
+ *dests = user_data.dests;
+
+ return (user_data.num_dests);
+ }
+
+
+## Basic Destination Information
+
+The `num_options` and `options` members of the `cups_dest_t` structure provide
+basic attributes about the destination in addition to the user default options
+and values for that destination. The following names are predefined for various
+destination attributes:
+
+- "auth-info-required": The type of authentication required for printing to this
+ destination: "none", "username,password", "domain,username,password", or
+ "negotiate" (Kerberos).
+- "printer-info": The human-readable description of the destination such as "My
+ Laser Printer".
+- "printer-is-accepting-jobs": "true" if the destination is accepting new jobs,
+ "false" otherwise.
+- "printer-is-shared": "true" if the destination is being shared with other
+ computers, "false" otherwise.
+- "printer-location": The human-readable location of the destination such as
+ "Lab 4".
+- "printer-make-and-model": The human-readable make and model of the destination
+ such as "ExampleCorp LaserPrinter 4000 Series".
+- "printer-state": "3" if the destination is idle, "4" if the destination is
+ printing a job, and "5" if the destination is stopped.
+- "printer-state-change-time": The UNIX time when the destination entered the
+ current state.
+- "printer-state-reasons": Additional comma-delimited state keywords for the
+ destination such as "media-tray-empty-error" and "toner-low-warning".
+- "printer-type": The `cups_ptype_t` value associated with the destination.
+- "printer-uri-supported": The URI associated with the destination; if not set,
+ this destination was discovered but is not yet setup as a local printer.
+
+Use the `cupsGetOption` function to retrieve the value. For example, the
+following code gets the make and model of a destination:
+
+ const char *model = cupsGetOption("printer-make-and-model",
+ dest->num_options,
+ dest->options);
+
+
+## Detailed Destination Information
+
+Once a destination has been chosen, the `cupsCopyDestInfo` function can be used
+to gather detailed information about the destination:
+
+ cups_dinfo_t *
+ cupsCopyDestInfo(http_t *http, cups_dest_t *dest);
+
+The `http` argument specifies a connection to the CUPS scheduler and is
+typically the constant `CUPS_HTTP_DEFAULT`. The `dest` argument specifies the
+destination to query.
+
+The `cups_dinfo_t` structure that is returned contains a snapshot of the
+supported options and their supported, ready, and default values. It also can
+report constraints between different options and values, and recommend changes
+to resolve those constraints.
+
+
+### Getting Supported Options and Values
+
+The `cupsCheckDestSupported` function can be used to test whether a particular
+option or option and value is supported:
+
+ int
+ cupsCheckDestSupported(http_t *http, cups_dest_t *dest,
+ cups_dinfo_t *info,
+ const char *option,
+ const char *value);
+
+The `option` argument specifies the name of the option to check. The following
+constants can be used to check the various standard options:
+
+- `CUPS_COPIES`: Controls the number of copies that are produced.
+- `CUPS_FINISHINGS`: A comma-delimited list of integer constants that control
+ the finishing processes that are applied to the job, including stapling,
+ punching, and folding.
+- `CUPS_MEDIA`: Controls the media size that is used, typically one of the
+ following: `CUPS_MEDIA_3X5`, `CUPS_MEDIA_4X6`, `CUPS_MEDIA_5X7`,
+ `CUPS_MEDIA_8X10`, `CUPS_MEDIA_A3`, `CUPS_MEDIA_A4`, `CUPS_MEDIA_A5`,
+ `CUPS_MEDIA_A6`, `CUPS_MEDIA_ENV10`, `CUPS_MEDIA_ENVDL`, `CUPS_MEDIA_LEGAL`,
+ `CUPS_MEDIA_LETTER`, `CUPS_MEDIA_PHOTO_L`, `CUPS_MEDIA_SUPERBA3`, or
+ `CUPS_MEDIA_TABLOID`.
+- `CUPS_MEDIA_SOURCE`: Controls where the media is pulled from, typically either
+ `CUPS_MEDIA_SOURCE_AUTO` or `CUPS_MEDIA_SOURCE_MANUAL`.
+- `CUPS_MEDIA_TYPE`: Controls the type of media that is used, typically one of
+ the following: `CUPS_MEDIA_TYPE_AUTO`, `CUPS_MEDIA_TYPE_ENVELOPE`,
+ `CUPS_MEDIA_TYPE_LABELS`, `CUPS_MEDIA_TYPE_LETTERHEAD`,
+ `CUPS_MEDIA_TYPE_PHOTO`, `CUPS_MEDIA_TYPE_PHOTO_GLOSSY`,
+ `CUPS_MEDIA_TYPE_PHOTO_MATTE`, `CUPS_MEDIA_TYPE_PLAIN`, or
+ `CUPS_MEDIA_TYPE_TRANSPARENCY`.
+- `CUPS_NUMBER_UP`: Controls the number of document pages that are placed on
+ each media side.
+- `CUPS_ORIENTATION`: Controls the orientation of document pages placed on the
+ media: `CUPS_ORIENTATION_PORTRAIT` or `CUPS_ORIENTATION_LANDSCAPE`.
+- `CUPS_PRINT_COLOR_MODE`: Controls whether the output is in color
+ \(`CUPS_PRINT_COLOR_MODE_COLOR`), grayscale
+ \(`CUPS_PRINT_COLOR_MODE_MONOCHROME`), or either
+ \(`CUPS_PRINT_COLOR_MODE_AUTO`).
+- `CUPS_PRINT_QUALITY`: Controls the generate quality of the output:
+ `CUPS_PRINT_QUALITY_DRAFT`, `CUPS_PRINT_QUALITY_NORMAL`, or
+ `CUPS_PRINT_QUALITY_HIGH`.
+- `CUPS_SIDES`: Controls whether prints are placed on one or both sides of the
+ media: `CUPS_SIDES_ONE_SIDED`, `CUPS_SIDES_TWO_SIDED_PORTRAIT`, or
+ `CUPS_SIDES_TWO_SIDED_LANDSCAPE`.
+
+If the `value` argument is `NULL`, the `cupsCheckDestSupported` function returns
+whether the option is supported by the destination. Otherwise, the function
+returns whether the specified value of the option is supported.
+
+The `cupsFindDestSupported` function returns the IPP attribute containing the
+supported values for a given option:
+
+ ipp_attribute_t *
+ cupsFindDestSupported(http_t *http, cups_dest_t *dest,
+ cups_dinfo_t *dinfo,
+ const char *option);
+
+For example, the following code prints the supported finishing processes for a
+destination, if any, to the standard output:
+
+ cups_dinfo_t *info = cupsCopyDestInfo(CUPS_HTTP_DEFAULT,
+ dest);
+
+ if (cupsCheckDestSupported(CUPS_HTTP_DEFAULT, dest, info,
+ CUPS_FINISHINGS, NULL))
+ {
+ ipp_attribute_t *finishings =
+ cupsFindDestSupported(CUPS_HTTP_DEFAULT, dest, info,
+ CUPS_FINISHINGS);
+ int i, count = ippGetCount(finishings);
+
+ puts("finishings supported:");
+ for (i = 0; i < count; i ++)
+ printf(" %d\n", ippGetInteger(finishings, i));
+ }
+ else
+ puts("finishings not supported.");
+
+The "job-creation-attributes" option can be queried to get a list of supported
+options. For example, the following code prints the list of supported options
+to the standard output:
+
+ ipp_attribute_t *attrs =
+ cupsFindDestSupported(CUPS_HTTP_DEFAULT, dest, info,
+ "job-creation-attributes");
+ int i, count = ippGetCount(attrs);
+
+ for (i = 0; i < count; i ++)
+ puts(ippGetString(attrs, i, NULL));
+
+
+### Getting Default Values
+
+There are two sets of default values - user defaults that are available via the
+`num_options` and `options` members of the `cups_dest_t` structure, and
+destination defaults that available via the `cups_dinfo_t` structure and the
+`cupsFindDestDefault` function which returns the IPP attribute containing the
+default value(s) for a given option:
+
+ ipp_attribute_t *
+ cupsFindDestDefault(http_t *http, cups_dest_t *dest,
+ cups_dinfo_t *dinfo,
+ const char *option);
+
+The user defaults from `cupsGetOption` should always take preference over the
+destination defaults. For example, the following code prints the default
+finishings value(s) to the standard output:
+
+ const char *def_value =
+ cupsGetOption(CUPS_FINISHINGS, dest->num_options,
+ dest->options);
+ ipp_attribute_t *def_attr =
+ cupsFindDestDefault(CUPS_HTTP_DEFAULT, dest, info,
+ CUPS_FINISHINGS);
+
+ if (def_value != NULL)
+ {
+ printf("Default finishings: %s\n", def_value);
+ }
+ else
+ {
+ int i, count = ippGetCount(def_attr);
+
+ printf("Default finishings: %d",
+ ippGetInteger(def_attr, 0));
+ for (i = 1; i < count; i ++)
+ printf(",%d", ippGetInteger(def_attr, i));
+ putchar('\n');
+ }
+
+
+### Getting Ready (Loaded) Values
+
+The finishings and media options also support queries for the ready, or loaded,
+values. For example, a printer may have punch and staple finishers installed
+but be out of staples - the supported values will list both punch and staple
+finishing processes but the ready values will only list the punch processes.
+Similarly, a printer may support hundreds of different sizes of media but only
+have a single size loaded at any given time - the ready values are limited to
+the media that is actually in the printer.
+
+The `cupsFindDestReady` function finds the IPP attribute containing the ready
+values for a given option:
+
+ ipp_attribute_t *
+ cupsFindDestReady(http_t *http, cups_dest_t *dest,
+ cups_dinfo_t *dinfo, const char *option);
+
+For example, the following code lists the ready finishing processes:
+
+ ipp_attribute_t *ready_finishings =
+ cupsFindDestReady(CUPS_HTTP_DEFAULT, dest, info,
+ CUPS_FINISHINGS);
+
+ if (ready_finishings != NULL)
+ {
+ int i, count = ippGetCount(ready_finishings);
+
+ puts("finishings ready:");
+ for (i = 0; i < count; i ++)
+ printf(" %d\n", ippGetInteger(ready_finishings, i));
+ }
+ else
+ puts("no finishings are ready.");
+
+
+### Media Size Options
+
+CUPS provides functions for querying the dimensions and margins for each of the
+supported media size options. The `cups_size_t` structure is used to describe a
+media size:
+
+ typedef struct cups_size_s
+ {
+ char media[128];
+ int width, length;
+ int bottom, left, right, top;
+ } cups_size_t;
+
+The `width` and `length` members specify the dimensions of the media in
+hundredths of millimeters (1/2540th of an inch). The `bottom`, `left`, `right`,
+and `top` members specify the margins of the printable area, also in hundredths
+of millimeters.
+
+The `cupsGetDestMediaByName` and `cupsGetDestMediaBySize` functions lookup the
+media size information using a standard media size name or dimensions in
+hundredths of millimeters:
+
+ int
+ cupsGetDestMediaByName(http_t *http, cups_dest_t *dest,
+ cups_dinfo_t *dinfo,
+ const char *media,
+ unsigned flags, cups_size_t *size);
+
+ int
+ cupsGetDestMediaBySize(http_t *http, cups_dest_t *dest,
+ cups_dinfo_t *dinfo,
+ int width, int length,
+ unsigned flags, cups_size_t *size);
+
+The `media`, `width`, and `length` arguments specify the size to lookup. The
+`flags` argument specifies a bitfield controlling various lookup options:
+
+- `CUPS_MEDIA_FLAGS_DEFAULT`: Find the closest size supported by the printer.
+- `CUPS_MEDIA_FLAGS_BORDERLESS`: Find a borderless size.
+- `CUPS_MEDIA_FLAGS_DUPLEX`: Find a size compatible with two-sided printing.
+- `CUPS_MEDIA_FLAGS_EXACT`: Find an exact match for the size.
+- `CUPS_MEDIA_FLAGS_READY`: If the printer supports media sensing or
+ configuration of the media in each tray/source, find the size amongst the
+ "ready" media.
+
+If a matching size is found for the destination, the size information is stored
+in the structure pointed to by the `size` argument and 1 is returned. Otherwise
+0 is returned.
+
+For example, the following code prints the margins for two-sided printing on US
+Letter media:
+
+ cups_size_t size;
+
+ if (cupsGetDestMediaByName(CUPS_HTTP_DEFAULT, dest, info,
+ CUPS_MEDIA_LETTER,
+ CUPS_MEDIA_FLAGS_DUPLEX, &size))
+ {
+ puts("Margins for duplex US Letter:");
+ printf(" Bottom: %.2fin\n", size.bottom / 2540.0);
+ printf(" Left: %.2fin\n", size.left / 2540.0);
+ printf(" Right: %.2fin\n", size.right / 2540.0);
+ printf(" Top: %.2fin\n", size.top / 2540.0);
+ }
+ else
+ puts("Margins for duplex US Letter are not available.");
+
+You can also enumerate all of the sizes that match a given `flags` value using
+the `cupsGetDestMediaByIndex` and `cupsGetDestMediaCount` functions:
+
+ int
+ cupsGetDestMediaByIndex(http_t *http, cups_dest_t *dest,
+ cups_dinfo_t *dinfo, int n,
+ unsigned flags, cups_size_t *size);
+
+ int
+ cupsGetDestMediaCount(http_t *http, cups_dest_t *dest,
+ cups_dinfo_t *dinfo, unsigned flags);
+
+For example, the following code prints the list of ready media and corresponding
+margins:
+
+ cups_size_t size;
+ int i;
+ int count = cupsGetDestMediaCount(CUPS_HTTP_DEFAULT,
+ dest, info,
+ CUPS_MEDIA_FLAGS_READY);
+
+ for (i = 0; i < count; i ++)
+ {
+ if (cupsGetDestMediaByIndex(CUPS_HTTP_DEFAULT, dest, info,
+ i, CUPS_MEDIA_FLAGS_READY,
+ &size))
+ {
+ printf("%s:\n", size.name);
+ printf(" Width: %.2fin\n", size.width / 2540.0);
+ printf(" Length: %.2fin\n", size.length / 2540.0);
+ printf(" Bottom: %.2fin\n", size.bottom / 2540.0);
+ printf(" Left: %.2fin\n", size.left / 2540.0);
+ printf(" Right: %.2fin\n", size.right / 2540.0);
+ printf(" Top: %.2fin\n", size.top / 2540.0);
+ }
+ }
+
+Finally, the `cupsGetDestMediaDefault` function returns the default media size:
+
+ int
+ cupsGetDestMediaDefault(http_t *http, cups_dest_t *dest,
+ cups_dinfo_t *dinfo, unsigned flags,
+ cups_size_t *size);
+
+
+### Localizing Options and Values
+
+CUPS provides three functions to get localized, human-readable strings in the
+user's current locale for options and values: `cupsLocalizeDestMedia`,
+`cupsLocalizeDestOption`, and `cupsLocalizeDestValue`:
+
+ const char *
+ cupsLocalizeDestMedia(http_t *http, cups_dest_t *dest,
+ cups_dinfo_t *info, unsigned flags,
+ cups_size_t *size);
+
+ const char *
+ cupsLocalizeDestOption(http_t *http, cups_dest_t *dest,
+ cups_dinfo_t *info,
+ const char *option);
+
+ const char *
+ cupsLocalizeDestValue(http_t *http, cups_dest_t *dest,
+ cups_dinfo_t *info,
+ const char *option, const char *value);
+
+
+## Submitting a Print Job
+
+Once you are ready to submit a print job, you create a job using the
+`cupsCreateDestJob` function:
+
+ ipp_status_t
+ cupsCreateDestJob(http_t *http, cups_dest_t *dest,
+ cups_dinfo_t *info, int *job_id,
+ const char *title, int num_options,
+ cups_option_t *options);
+
+The `title` argument specifies a name for the print job such as "My Document".
+The `num_options` and `options` arguments specify the options for the print
+job which are allocated using the `cupsAddOption` function.
+
+When successful, the job's numeric identifier is stored in the integer pointed
+to by the `job_id` argument and `IPP_STATUS_OK` is returned. Otherwise, an IPP
+error status is returned.
+
+For example, the following code creates a new job that will print 42 copies of a
+two-sided US Letter document:
+
+ int job_id = 0;
+ int num_options = 0;
+ cups_option_t *options = NULL;
+
+ num_options = cupsAddOption(CUPS_COPIES, "42",
+ num_options, &options);
+ num_options = cupsAddOption(CUPS_MEDIA, CUPS_MEDIA_LETTER,
+ num_options, &options);
+ num_options = cupsAddOption(CUPS_SIDES,
+ CUPS_SIDES_TWO_SIDED_PORTRAIT,
+ num_options, &options);
+
+ if (cupsCreateDestJob(CUPS_HTTP_DEFAULT, dest, info,
+ &job_id, "My Document", num_options,
+ options) == IPP_STATUS_OK)
+ printf("Created job: %d\n", job_id);
+ else
+ printf("Unable to create job: %s\n",
+ cupsLastErrorString());
+
+Once the job is created, you submit documents for the job using the
+`cupsStartDestDocument`, `cupsWriteRequestData`, and `cupsFinishDestDocument`
+functions:
+
+ http_status_t
+ cupsStartDestDocument(http_t *http, cups_dest_t *dest,
+ cups_dinfo_t *info, int job_id,
+ const char *docname,
+ const char *format,
+ int num_options,
+ cups_option_t *options,
+ int last_document);
+
+ http_status_t
+ cupsWriteRequestData(http_t *http, const char *buffer,
+ size_t length);
+
+ ipp_status_t
+ cupsFinishDestDocument(http_t *http, cups_dest_t *dest,
+ cups_dinfo_t *info);
+
+The `docname` argument specifies the name of the document, typically the
+original filename. The `format` argument specifies the MIME media type of the
+document, including the following constants:
+
+- `CUPS_FORMAT_JPEG`: "image/jpeg"
+- `CUPS_FORMAT_PDF`: "application/pdf"
+- `CUPS_FORMAT_POSTSCRIPT`: "application/postscript"
+- `CUPS_FORMAT_TEXT`: "text/plain"
+
+The `num_options` and `options` arguments specify per-document print options,
+which at present must be 0 and `NULL`. The `last_document` argument specifies
+whether this is the last document in the job.
+
+For example, the following code submits a PDF file to the job that was just
+created:
+
+ FILE *fp = fopen("filename.pdf", "rb");
+ size_t bytes;
+ char buffer[65536];
+
+ if (cupsStartDestDocument(CUPS_HTTP_DEFAULT, dest, info,
+ job_id, "filename.pdf", 0, NULL,
+ 1) == HTTP_STATUS_CONTINUE)
+ {
+ while ((bytes = fread(buffer, 1, sizeof(buffer), fp)) > 0)
+ if (cupsWriteRequestData(CUPS_HTTP_DEFAULT, buffer,
+ bytes) != HTTP_STATUS_CONTINUE)
+ break;
+
+ if (cupsFinishDestDocument(CUPS_HTTP_DEFAULT, dest,
+ info) == IPP_STATUS_OK)
+ puts("Document send succeeded.");
+ else
+ printf("Document send failed: %s\n",
+ cupsLastErrorString());
+ }
+
+ fclose(fp);
+
+
+# Sending IPP Requests
+
+CUPS provides a rich API for sending IPP requests to the scheduler or printers,
+typically from management or utility applications whose primary purpose is not
+to send print jobs.
+
+
+## Connecting to the Scheduler or Printer
+
+The connection to the scheduler or printer is represented by the HTTP connection
+type `http_t`. The `cupsConnectDest` function connects to the scheduler or
+printer associated with the destination:
+
+ http_t *
+ cupsConnectDest(cups_dest_t *dest, unsigned flags, int msec,
+ int *cancel, char *resource,
+ size_t resourcesize, cups_dest_cb_t cb,
+ void *user_data);
+
+The `dest` argument specifies the destination to connect to.
+
+The `flags` argument specifies whether you want to connect to the scheduler
+(`CUPS_DEST_FLAGS_NONE`) or device/printer (`CUPS_DEST_FLAGS_DEVICE`) associated
+with the destination.
+
+The `msec` argument specifies how long you are willing to wait for the
+connection to be established in milliseconds. Specify a value of `-1` to wait
+indefinitely.
+
+The `cancel` argument specifies the address of an integer variable that can be
+set to a non-zero value to cancel the connection. Specify a value of `NULL`
+to not provide a cancel variable.
+
+The `resource` and `resourcesize` arguments specify the address and size of a
+character string array to hold the path to use when sending an IPP request.
+
+The `cb` and `user_data` arguments specify a destination callback function that
+returns 1 to continue connecting or 0 to stop. The destination callback work
+the same way as the one used for the `cupsEnumDests` function.
+
+On success, a HTTP connection is returned that can be used to send IPP requests
+and get IPP responses.
+
+For example, the following code connects to the printer associated with a
+destination with a 30 second timeout:
+
+ char resource[256];
+ http_t *http = cupsConnectDest(dest, CUPS_DEST_FLAGS_DEVICE,
+ 30000, NULL, resource,
+ sizeof(resource), NULL, NULL);
+
+
+## Creating an IPP Request
+
+IPP requests are represented by the IPP message type `ipp_t` and each IPP
+attribute in the request is representing using the type `ipp_attribute_t`. Each
+IPP request includes an operation code (`IPP_OP_CREATE_JOB`,
+`IPP_OP_GET_PRINTER_ATTRIBUTES`, etc.) and a 32-bit integer identifier.
+
+The `ippNewRequest` function creates a new IPP request:
+
+ ipp_t *
+ ippNewRequest(ipp_op_t op);
+
+The `op` argument specifies the IPP operation code for the request. For
+example, the following code creates an IPP Get-Printer-Attributes request:
+
+ ipp_t *request = ippNewRequest(IPP_OP_GET_PRINTER_ATTRIBUTES);
+
+The request identifier is automatically set to a unique value for the current
+process.
+
+Each IPP request starts with two IPP attributes, "attributes-charset" and
+"attributes-natural-language", followed by IPP attribute(s) that specify the
+target of the operation. The `ippNewRequest` automatically adds the correct
+"attributes-charset" and "attributes-natural-language" attributes, but you must
+add the target attribute(s). For example, the following code adds the
+"printer-uri" attribute to the IPP Get-Printer-Attributes request to specify
+which printer is being queried:
+
+ const char *printer_uri = cupsGetOption("device-uri",
+ dest->num_options,
+ dest->options);
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
+ "printer-uri", NULL, printer_uri);
+
+> Note: If we wanted to query the scheduler instead of the device, we would look
+> up the "printer-uri-supported" option instead of the "device-uri" value.
+
+The `ippAddString` function adds the "printer-uri" attribute the the IPP
+request. The `IPP_TAG_OPERATION` argument specifies that the attribute is part
+of the operation. The `IPP_TAG_URI` argument specifies that the value is a
+Universal Resource Identifier (URI) string. The `NULL` argument specifies there
+is no language (English, French, Japanese, etc.) associated with the string, and
+the `printer_uri` argument specifies the string value.
+
+The IPP Get-Printer-Attributes request also supports an IPP attribute called
+"requested-attributes" that lists the attributes and values you are interested
+in. For example, the following code requests the printer state attributes:
+
+ static const char * const requested_attributes[] =
+ {
+ "printer-state",
+ "printer-state-message",
+ "printer-state-reasons"
+ };
+
+ ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
+ "requested-attributes", 3, NULL,
+ requested_attributes);
+
+The `ippAddStrings` function adds an attribute with one or more strings, in this
+case three. The `IPP_TAG_KEYWORD` argument specifies that the strings are
+keyword values, which are used for attribute names. All strings use the same
+language (`NULL`), and the attribute will contain the three strings in the
+array `requested_attributes`.
+
+CUPS provides many functions to adding attributes of different types:
+
+- `ippAddBoolean` adds a boolean (`IPP_TAG_BOOLEAN`) attribute with one value.
+- `ippAddInteger` adds an enum (`IPP_TAG_ENUM`) or integer (`IPP_TAG_INTEGER`)
+ attribute with one value.
+- `ippAddIntegers` adds an enum or integer attribute with one or more values.
+- `ippAddOctetString` adds an octetString attribute with one value.
+- `ippAddOutOfBand` adds a admin-defined (`IPP_TAG_ADMINDEFINE`), default
+ (`IPP_TAG_DEFAULT`), delete-attribute (`IPP_TAG_DELETEATTR`), no-value
+ (`IPP_TAG_NOVALUE`), not-settable (`IPP_TAG_NOTSETTABLE`), unknown
+ (`IPP_TAG_UNKNOWN`), or unsupported (`IPP_TAG_UNSUPPORTED_VALUE`) out-of-band
+ attribute.
+- `ippAddRange` adds a rangeOfInteger attribute with one range.
+- `ippAddRanges` adds a rangeOfInteger attribute with one or more ranges.
+- `ippAddResolution` adds a resolution attribute with one resolution.
+- `ippAddResolutions` adds a resolution attribute with one or more resolutions.
+- `ippAddString` adds a charset (`IPP_TAG_CHARSET`), keyword (`IPP_TAG_KEYWORD`),
+ mimeMediaType (`IPP_TAG_MIMETYPE`), name (`IPP_TAG_NAME` and
+ `IPP_TAG_NAMELANG`), naturalLanguage (`IPP_TAG_NATURAL_LANGUAGE`), text
+ (`IPP_TAG_TEXT` and `IPP_TAG_TEXTLANG`), uri (`IPP_TAG_URI`), or uriScheme
+ (`IPP_TAG_URISCHEME`) attribute with one value.
+- `ippAddStrings` adds a charset, keyword, mimeMediaType, name, naturalLanguage,
+ text, uri, or uriScheme attribute with one or more values.
+
+
+## Sending the IPP Request
+
+Once you have created the IPP request, you can send it using the
+`cupsDoRequest` function. For example, the following code sends the IPP
+Get-Printer-Attributes request to the destination and saves the response:
+
+ ipp_t *response = cupsDoRequest(http, request, resource);
+
+For requests like Send-Document that include a file, the `cupsDoFileRequest`
+function should be used:
+
+ ipp_t *response = cupsDoFileRequest(http, request, resource,
+ filename);
+
+Both `cupsDoRequest` and `cupsDoFileRequest` free the IPP request. If a valid
+IPP response is received, it is stored in a new IPP message (`ipp_t`) and
+returned to the caller. Otherwise `NULL` is returned.
+
+The status from the most recent request can be queried using the `cupsLastError`
+function, for example:
+
+ if (cupsLastError() >= IPP_STATUS_ERROR_BAD_REQUEST)
+ {
+ /* request failed */
+ }
+
+A human-readable error message is also available using the `cupsLastErrorString`
+function:
+
+ if (cupsLastError() >= IPP_STATUS_ERROR_BAD_REQUEST)
+ {
+ /* request failed */
+ printf("Request failed: %s\n", cupsLastErrorString());
+ }
+
+
+## Processing the IPP Response
+
+Each response to an IPP request is also an IPP message (`ipp_t`) with its own
+IPP attributes (`ipp_attribute_t`) that includes a status code (`IPP_STATUS_OK`,
+`IPP_STATUS_ERROR_BAD_REQUEST`, etc.) and the corresponding 32-bit integer
+identifier from the request.
+
+For example, the following code finds the printer state attributes and prints
+their values:
+
+ ipp_attribute_t *attr;
+
+ if ((attr = ippFindAttribute(response, "printer-state",
+ IPP_TAG_ENUM)) != NULL)
+ {
+ printf("printer-state=%s\n",
+ ippEnumString("printer-state", ippGetInteger(attr, 0)));
+ }
+ else
+ puts("printer-state=unknown");
+
+ if ((attr = ippFindAttribute(response, "printer-state-message",
+ IPP_TAG_TEXT)) != NULL)
+ {
+ printf("printer-state-message=\"%s\"\n",
+ ippGetString(attr, 0, NULL)));
+ }
+
+ if ((attr = ippFindAttribute(response, "printer-state-reasons",
+ IPP_TAG_KEYWORD)) != NULL)
+ {
+ int i, count = ippGetCount(attr);
+
+ puts("printer-state-reasons=");
+ for (i = 0; i < count; i ++)
+ printf(" %s\n", ippGetString(attr, i, NULL)));
+ }
+
+The `ippGetCount` function returns the number of values in an attribute.
+
+The `ippGetInteger` and `ippGetString` functions return a single integer or
+string value from an attribute.
+
+The `ippEnumString` function converts a enum value to its keyword (string)
+equivalent.
+
+Once you are done using the IPP response message, free it using the `ippDelete`
+function:
+
+ ippDelete(response);
+
+
+## Authentication
+
+CUPS normally handles authentication through the console. GUI applications
+should set a password callback using the `cupsSetPasswordCB2` function:
+
+ void
+ cupsSetPasswordCB2(cups_password_cb2_t cb, void *user_data);
+
+The password callback will be called when needed and is responsible for setting
+the current user name using `cupsSetUser` and returning a string:
+
+ const char *
+ cups_password_cb2(const char *prompt, http_t *http,
+ const char *method, const char *resource,
+ void *user_data);
+
+The `prompt` argument is a string from CUPS that should be displayed to the
+user.
+
+The `http` argument is the connection hosting the request that is being
+authenticated. The password callback can call the `httpGetField` and
+`httpGetSubField` functions to look for additional details concerning the
+authentication challenge.
+
+The `method` argument specifies the HTTP method used for the request and is
+typically "POST".
+
+The `resource` argument specifies the path used for the request.
+
+The `user_data` argument provides the user data pointer from the
+`cupsSetPasswordCB2` call.
diff --git a/cups/cupspm.opacity b/cups/cupspm.opacity
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/cups/cupspm.opacity
diff --git a/cups/cupspm.png b/cups/cupspm.png
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/cups/cupspm.png
diff --git a/cups/dest-job.c b/cups/dest-job.c
index b0d89b6e..f12b1dc5 100644
--- a/cups/dest-job.c
+++ b/cups/dest-job.c
@@ -1,7 +1,7 @@
/*
* Destination job support for CUPS.
*
- * Copyright 2012-2016 by Apple Inc.
+ * Copyright 2012-2017 by Apple Inc.
*
* These coded instructions, statements, and computer programs are the
* property of Apple Inc. and are protected by Federal copyright
@@ -25,13 +25,13 @@
* The "job_id" is the number returned by cupsCreateDestJob.
*
* Returns @code IPP_STATUS_OK@ on success and
- * @code IPP_STATUS_ERRPR_NOT_AUTHORIZED@ or
+ * @code IPP_STATUS_ERROR_NOT_AUTHORIZED@ or
* @code IPP_STATUS_ERROR_FORBIDDEN@ on failure.
*
* @since CUPS 1.6/macOS 10.8@
*/
-ipp_status_t
+ipp_status_t /* O - Status of cancel operation */
cupsCancelDestJob(http_t *http, /* I - Connection to destination */
cups_dest_t *dest, /* I - Destination */
int job_id) /* I - Job ID */
@@ -84,6 +84,13 @@ cupsCloseDestJob(
DEBUG_printf(("cupsCloseDestJob(http=%p, dest=%p(%s/%s), info=%p, job_id=%d)", (void *)http, (void *)dest, dest ? dest->name : NULL, dest ? dest->instance : NULL, (void *)info, job_id));
/*
+ * Get the default connection as needed...
+ */
+
+ if (!http)
+ http = _cupsConnect();
+
+ /*
* Range check input...
*/
@@ -172,6 +179,13 @@ cupsCreateDestJob(
"job_id=%p, title=\"%s\", num_options=%d, options=%p)", (void *)http, (void *)dest, dest ? dest->name : NULL, dest ? dest->instance : NULL, (void *)info, (void *)job_id, title, num_options, (void *)options));
/*
+ * Get the default connection as needed...
+ */
+
+ if (!http)
+ http = _cupsConnect();
+
+ /*
* Range check input...
*/
@@ -252,6 +266,13 @@ cupsFinishDestDocument(
DEBUG_printf(("cupsFinishDestDocument(http=%p, dest=%p(%s/%s), info=%p)", (void *)http, (void *)dest, dest ? dest->name : NULL, dest ? dest->instance : NULL, (void *)info));
/*
+ * Get the default connection as needed...
+ */
+
+ if (!http)
+ http = _cupsConnect();
+
+ /*
* Range check input...
*/
@@ -307,6 +328,13 @@ cupsStartDestDocument(
DEBUG_printf(("cupsStartDestDocument(http=%p, dest=%p(%s/%s), info=%p, job_id=%d, docname=\"%s\", format=\"%s\", num_options=%d, options=%p, last_document=%d)", (void *)http, (void *)dest, dest ? dest->name : NULL, dest ? dest->instance : NULL, (void *)info, job_id, docname, format, num_options, (void *)options, last_document));
/*
+ * Get the default connection as needed...
+ */
+
+ if (!http)
+ http = _cupsConnect();
+
+ /*
* Range check input...
*/
diff --git a/cups/dest-localization.c b/cups/dest-localization.c
index 6d75a972..fceaad29 100644
--- a/cups/dest-localization.c
+++ b/cups/dest-localization.c
@@ -60,12 +60,15 @@ cupsLocalizeDestMedia(
*ltype; /* Localized media type */
+ DEBUG_printf(("cupsLocalizeDestMedia(http=%p, dest=%p, dinfo=%p, flags=%x, size=%p(\"%s\"))", (void *)http, (void *)dest, (void *)dinfo, flags, (void *)size, size ? size->media : "(null)"));
+
/*
* Range check input...
*/
if (!http || !dest || !dinfo || !size)
{
+ DEBUG_puts("1cupsLocalizeDestMedia: Returning NULL.");
_cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(EINVAL), 0);
return (NULL);
}
@@ -79,13 +82,24 @@ cupsLocalizeDestMedia(
key.id = size->media;
if ((match = (_cups_message_t *)cupsArrayFind(dinfo->localizations, &key)) != NULL)
+ {
+ DEBUG_printf(("1cupsLocalizeDestMedia: Returning \"%s\".", match->str));
return (match->str);
+ }
/*
* If not, get the localized size, source, and type strings...
*/
lang = cupsLangDefault();
+
+ snprintf(temp, sizeof(temp), "media.%s", size->media);
+ if ((lsize = _cupsLangString(lang, temp)) != NULL && strcmp(lsize, temp))
+ {
+ DEBUG_printf(("1cupsLocalizeDestMedia: Returning standard localization \"%s\".", lsize));
+ return (lsize);
+ }
+
pwg = pwgMediaForSize(size->width, size->length);
if (pwg->ppd)
@@ -101,7 +115,7 @@ cupsLocalizeDestMedia(
* Use inches since the size is a multiple of 1/4 inch.
*/
- snprintf(temp, sizeof(temp), _cupsLangString(lang, _("%g x %g")), size->width / 2540.0, size->length / 2540.0);
+ snprintf(temp, sizeof(temp), _cupsLangString(lang, _("%g x %g \"")), size->width / 2540.0, size->length / 2540.0);
}
else
{
@@ -189,6 +203,8 @@ cupsLocalizeDestMedia(
cupsArrayAdd(dinfo->localizations, match);
+ DEBUG_printf(("1cupsLocalizeDestMedia: Returning \"%s\".", match->str));
+
return (match->str);
}
@@ -212,7 +228,10 @@ cupsLocalizeDestOption(
{
_cups_message_t key, /* Search key */
*match; /* Matching entry */
+ const char *localized; /* Localized string */
+
+ DEBUG_printf(("cupsLocalizeDestOption(http=%p, dest=%p, dinfo=%p, option=\"%s\")", (void *)http, (void *)dest, (void *)dinfo, option));
if (!http || !dest || !dinfo)
return (option);
@@ -220,13 +239,12 @@ cupsLocalizeDestOption(
if (!dinfo->localizations)
cups_create_localizations(http, dinfo);
- if (cupsArrayCount(dinfo->localizations) == 0)
- return (option);
-
key.id = (char *)option;
if ((match = (_cups_message_t *)cupsArrayFind(dinfo->localizations,
&key)) != NULL)
return (match->str);
+ else if ((localized = _cupsLangString(cupsLangDefault(), option)) != NULL)
+ return (localized);
else
return (option);
}
@@ -253,22 +271,40 @@ cupsLocalizeDestValue(
_cups_message_t key, /* Search key */
*match; /* Matching entry */
char pair[256]; /* option.value pair */
+ const char *localized; /* Localized string */
+ DEBUG_printf(("cupsLocalizeDestValue(http=%p, dest=%p, dinfo=%p, option=\"%s\", value=\"%s\")", (void *)http, (void *)dest, (void *)dinfo, option, value));
+
if (!http || !dest || !dinfo)
return (value);
+ if (!strcmp(option, "media"))
+ {
+ pwg_media_t *media = pwgMediaForPWG(value);
+ cups_size_t size;
+
+ strlcpy(size.media, value, sizeof(size.media));
+ size.width = media ? media->width : 0;
+ size.length = media ? media->length : 0;
+ size.left = 0;
+ size.right = 0;
+ size.bottom = 0;
+ size.top = 0;
+
+ return (cupsLocalizeDestMedia(http, dest, dinfo, CUPS_MEDIA_FLAGS_DEFAULT, &size));
+ }
+
if (!dinfo->localizations)
cups_create_localizations(http, dinfo);
- if (cupsArrayCount(dinfo->localizations) == 0)
- return (value);
-
snprintf(pair, sizeof(pair), "%s.%s", option, value);
key.id = pair;
if ((match = (_cups_message_t *)cupsArrayFind(dinfo->localizations,
&key)) != NULL)
return (match->str);
+ else if ((localized = _cupsLangString(cupsLangDefault(), pair)) != NULL && strcmp(localized, pair))
+ return (localized);
else
return (value);
}
diff --git a/cups/dest-options.c b/cups/dest-options.c
index bf9020ba..51705a50 100644
--- a/cups/dest-options.c
+++ b/cups/dest-options.c
@@ -1,7 +1,7 @@
/*
* Destination option/media support for CUPS.
*
- * Copyright 2012-2016 by Apple Inc.
+ * Copyright 2012-2017 by Apple Inc.
*
* These coded instructions, statements, and computer programs are the
* property of Apple Inc. and are protected by Federal copyright
@@ -73,7 +73,7 @@ cupsCheckDestSupported(
cups_dest_t *dest, /* I - Destination */
cups_dinfo_t *dinfo, /* I - Destination information */
const char *option, /* I - Option */
- const char *value) /* I - Value */
+ const char *value) /* I - Value or @code NULL@ */
{
int i; /* Looping var */
char temp[1024]; /* Temporary string */
@@ -86,10 +86,17 @@ cupsCheckDestSupported(
/*
+ * Get the default connection as needed...
+ */
+
+ if (!http)
+ http = _cupsConnect();
+
+ /*
* Range check input...
*/
- if (!http || !dest || !dinfo || !option || !value)
+ if (!http || !dest || !dinfo || !option)
return (0);
/*
@@ -107,7 +114,10 @@ cupsCheckDestSupported(
if (!attr)
return (0);
- /*
+ if (!value)
+ return (1);
+
+/*
* Compare values...
*/
@@ -316,6 +326,13 @@ cupsCopyDestConflicts(
*resolved = NULL;
/*
+ * Get the default connection as needed...
+ */
+
+ if (!http)
+ http = _cupsConnect();
+
+ /*
* Range check input...
*/
@@ -575,6 +592,13 @@ cupsCopyDestInfo(
DEBUG_printf(("cupsCopyDestSupported(http=%p, dest=%p(%s))", (void *)http, (void *)dest, dest ? dest->name : ""));
/*
+ * Get the default connection as needed...
+ */
+
+ if (!http)
+ http = _cupsConnect();
+
+ /*
* Range check input...
*/
@@ -686,6 +710,13 @@ cupsFindDestDefault(
/*
+ * Get the default connection as needed...
+ */
+
+ if (!http)
+ http = _cupsConnect();
+
+ /*
* Range check input...
*/
@@ -727,6 +758,13 @@ cupsFindDestReady(
/*
+ * Get the default connection as needed...
+ */
+
+ if (!http)
+ http = _cupsConnect();
+
+ /*
* Range check input...
*/
@@ -770,6 +808,13 @@ cupsFindDestSupported(
/*
+ * Get the default connection as needed...
+ */
+
+ if (!http)
+ http = _cupsConnect();
+
+ /*
* Range check input...
*/
@@ -791,6 +836,8 @@ cupsFindDestSupported(
/*
* 'cupsFreeDestInfo()' - Free destination information obtained using
* @link cupsCopyDestInfo@.
+ *
+ * @since CUPS 1.6/macOS 10.8@
*/
void
@@ -852,6 +899,13 @@ cupsGetDestMediaByIndex(
/*
+ * Get the default connection as needed...
+ */
+
+ if (!http)
+ http = _cupsConnect();
+
+ /*
* Range check input...
*/
@@ -940,6 +994,13 @@ cupsGetDestMediaByName(
/*
+ * Get the default connection as needed...
+ */
+
+ if (!http)
+ http = _cupsConnect();
+
+ /*
* Range check input...
*/
@@ -1008,6 +1069,13 @@ cupsGetDestMediaBySize(
/*
+ * Get the default connection as needed...
+ */
+
+ if (!http)
+ http = _cupsConnect();
+
+ /*
* Range check input...
*/
@@ -1059,6 +1127,13 @@ cupsGetDestMediaCount(
unsigned flags) /* I - Media flags */
{
/*
+ * Get the default connection as needed...
+ */
+
+ if (!http)
+ http = _cupsConnect();
+
+ /*
* Range check input...
*/
@@ -1104,6 +1179,13 @@ cupsGetDestMediaDefault(
/*
+ * Get the default connection as needed...
+ */
+
+ if (!http)
+ http = _cupsConnect();
+
+ /*
* Range check input...
*/
diff --git a/cups/dest.c b/cups/dest.c
index b06a9ee1..57a8dc95 100644
--- a/cups/dest.c
+++ b/cups/dest.c
@@ -1,7 +1,7 @@
/*
* User-defined destination (and option) support for CUPS.
*
- * Copyright 2007-2016 by Apple Inc.
+ * Copyright 2007-2017 by Apple Inc.
* Copyright 1997-2007 by Easy Software Products.
*
* These coded instructions, statements, and computer programs are the
@@ -60,6 +60,13 @@
# define kUseLastPrinter CFSTR("UseLastPrinter")
#endif /* __APPLE__ */
+#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
+# define _CUPS_DNSSD_GET_DESTS 250 /* Milliseconds for cupsGetDests */
+# define _CUPS_DNSSD_MAXTIME 50 /* Milliseconds for maximum quantum of time */
+#else
+# define _CUPS_DNSSD_GET_DESTS 0 /* Milliseconds for cupsGetDests */
+#endif /* HAVE_DNSSD || HAVE_AVAHI */
+
/*
* Types...
@@ -85,6 +92,7 @@ typedef struct _cups_dnssd_data_s /* Enumeration data */
AvahiSimplePoll *simple_poll; /* Polling interface */
AvahiClient *client; /* Client information */
int got_data; /* Did we get data? */
+ int browsers; /* How many browsers are running? */
# endif /* HAVE_DNSSD */
cups_dest_cb_t cb; /* Callback */
void *user_data; /* User data pointer */
@@ -101,9 +109,9 @@ typedef struct _cups_dnssd_device_s /* Enumerated device */
# else /* HAVE_AVAHI */
AvahiRecordBrowser *ref; /* Browser for query */
# endif /* HAVE_DNSSD */
- char *domain, /* Domain name */
- *fullName, /* Full name */
- *regtype; /* Registration type */
+ char *fullName, /* Full name */
+ *regtype, /* Registration type */
+ *domain; /* Domain name */
cups_ptype_t type; /* Device registration type */
cups_dest_t dest; /* Destination record */
} _cups_dnssd_device_t;
@@ -115,6 +123,18 @@ typedef struct _cups_dnssd_resolve_s /* Data for resolving URI */
} _cups_dnssd_resolve_t;
#endif /* HAVE_DNSSD */
+typedef struct _cups_getdata_s
+{
+ int num_dests; /* Number of destinations */
+ cups_dest_t *dests; /* Destinations */
+} _cups_getdata_t;
+
+typedef struct _cups_namedata_s
+{
+ const char *name; /* Named destination */
+ cups_dest_t *dest; /* Destination */
+} _cups_namedata_t;
+
/*
* Local functions...
@@ -208,10 +228,13 @@ static const char *cups_dnssd_resolve(cups_dest_t *dest, const char *uri,
static int cups_dnssd_resolve_cb(void *context);
static void cups_dnssd_unquote(char *dst, const char *src,
size_t dstsize);
+static int cups_elapsed(struct timeval *t);
#endif /* HAVE_DNSSD || HAVE_AVAHI */
+static int cups_enum_dests(http_t *http, unsigned flags, int msec, int *cancel, cups_ptype_t type, cups_ptype_t mask, cups_dest_cb_t cb, void *user_data);
static int cups_find_dest(const char *name, const char *instance,
int num_dests, cups_dest_t *dests, int prev,
int *rdiff);
+static int cups_get_cb(_cups_getdata_t *data, unsigned flags, cups_dest_t *dest);
static char *cups_get_default(const char *filename, char *namebuf,
size_t namesize, const char **instance);
static int cups_get_dests(const char *filename, const char *match_name,
@@ -219,6 +242,8 @@ static int cups_get_dests(const char *filename, const char *match_name,
int num_dests, cups_dest_t **dests);
static char *cups_make_string(ipp_attribute_t *attr, char *buffer,
size_t bufsize);
+static int cups_name_cb(_cups_namedata_t *data, unsigned flags, cups_dest_t *dest);
+static void cups_queue_name(char *name, const char *serviceName, size_t namesize);
/*
@@ -549,18 +574,24 @@ _cupsAppleSetUseLastPrinter(
/*
- * 'cupsConnectDest()' - Connect to the server for a destination.
+ * 'cupsConnectDest()' - Open a conection to the destination.
+ *
+ * Connect to the destination, returning a new @code http_t@ connection object
+ * and optionally the resource path to use for the destination. These calls
+ * will block until a connection is made, the timeout expires, the integer
+ * pointed to by "cancel" is non-zero, or the callback function (or block)
+ * returns 0. The caller is responsible for calling @link httpClose@ on the
+ * returned connection.
*
- * Connect to the destination, returning a new http_t connection object and
- * optionally the resource path to use for the destination. These calls will
- * block until a connection is made, the timeout expires, the integer pointed
- * to by "cancel" is non-zero, or the callback function (or block) returns 0,
- * The caller is responsible for calling httpClose() on the returned object.
+ * Starting with CUPS 2.2.4, the caller can pass @code CUPS_DEST_FLAGS_DEVICE@
+ * for the "flags" argument to connect directly to the device associated with
+ * the destination. Otherwise, the connection is made to the CUPS scheduler
+ * associated with the destination.
*
* @since CUPS 1.6/macOS 10.8@
*/
-http_t * /* O - Connection to server or @code NULL@ */
+http_t * /* O - Connection to destination or @code NULL@ */
cupsConnectDest(
cups_dest_t *dest, /* I - Destination */
unsigned flags, /* I - Connection flags */
@@ -608,17 +639,24 @@ cupsConnectDest(
* Grab the printer URI...
*/
- if ((uri = cupsGetOption("printer-uri-supported", dest->num_options, dest->options)) == NULL)
+ if (flags & CUPS_DEST_FLAGS_DEVICE)
{
- if ((uri = cupsGetOption("resolved-device-uri", dest->num_options, dest->options)) == NULL)
+ if ((uri = cupsGetOption("device-uri", dest->num_options, dest->options)) != NULL)
{
- if ((uri = cupsGetOption("device-uri", dest->num_options, dest->options)) != NULL)
- {
#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
- if (strstr(uri, "._tcp"))
- uri = cups_dnssd_resolve(dest, uri, msec, cancel, cb, user_data);
+ if (strstr(uri, "._tcp"))
+ uri = cups_dnssd_resolve(dest, uri, msec, cancel, cb, user_data);
+#endif /* HAVE_DNSSD || HAVE_AVAHI */
+ }
+ }
+ else if ((uri = cupsGetOption("printer-uri-supported", dest->num_options, dest->options)) == NULL)
+ {
+ if ((uri = cupsGetOption("device-uri", dest->num_options, dest->options)) != NULL)
+ {
+#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
+ if (strstr(uri, "._tcp"))
+ uri = cups_dnssd_resolve(dest, uri, msec, cancel, cb, user_data);
#endif /* HAVE_DNSSD || HAVE_AVAHI */
- }
}
if (uri)
@@ -725,18 +763,23 @@ cupsConnectDest(
#ifdef __BLOCKS__
/*
- * 'cupsConnectDestBlock()' - Connect to the server for a destination.
+ * 'cupsConnectDestBlock()' - Open a connection to the destination.
*
- * Connect to the destination, returning a new http_t connection object and
- * optionally the resource path to use for the destination. These calls will
- * block until a connection is made, the timeout expires, the integer pointed
- * to by "cancel" is non-zero, or the callback function (or block) returns 0,
- * The caller is responsible for calling httpClose() on the returned object.
+ * Connect to the destination, returning a new @code http_t@ connection object
+ * and optionally the resource path to use for the destination. These calls
+ * will block until a connection is made, the timeout expires, the integer
+ * pointed to by "cancel" is non-zero, or the block returns 0. The caller is
+ * responsible for calling @link httpClose@ on the returned connection.
*
- * @since CUPS 1.6/macOS 10.8@
+ * Starting with CUPS 2.2.4, the caller can pass @code CUPS_DEST_FLAGS_DEVICE@
+ * for the "flags" argument to connect directly to the device associated with
+ * the destination. Otherwise, the connection is made to the CUPS scheduler
+ * associated with the destination.
+ *
+ * @since CUPS 1.6/macOS 10.8@ @exclude all@
*/
-http_t * /* O - Connection to server or @code NULL@ */
+http_t * /* O - Connection to destination or @code NULL@ */
cupsConnectDestBlock(
cups_dest_t *dest, /* I - Destination */
unsigned flags, /* I - Connection flags */
@@ -762,10 +805,10 @@ cupsConnectDestBlock(
* @since CUPS 1.6/macOS 10.8@
*/
-int
-cupsCopyDest(cups_dest_t *dest,
- int num_dests,
- cups_dest_t **dests)
+int /* O - New number of destinations */
+cupsCopyDest(cups_dest_t *dest, /* I - Destination to copy */
+ int num_dests, /* I - Number of destinations */
+ cups_dest_t **dests) /* IO - Destination array */
{
int i; /* Looping var */
cups_dest_t *new_dest; /* New destination pointer */
@@ -907,334 +950,36 @@ _cupsCreateDest(const char *name, /* I - Printer name */
/*
* 'cupsEnumDests()' - Enumerate available destinations with a callback function.
*
- * Destinations are enumerated from one or more sources. The callback function
- * receives the @code user_data@ pointer, destination name, instance, number of
- * options, and options which can be used as input to the @link cupsAddDest@
- * function. The function must return 1 to continue enumeration or 0 to stop.
+ * Destinations are enumerated from one or more sources. The callback function
+ * receives the @code user_data@ pointer and the destination pointer which can
+ * be used as input to the @link cupsCopyDest@ function. The function must
+ * return 1 to continue enumeration or 0 to stop.
+ *
+ * The @code type@ and @code mask@ arguments allow the caller to filter the
+ * destinations that are enumerated. Passing 0 for both will enumerate all
+ * printers. The constant @code CUPS_PRINTER_DISCOVERED@ is used to filter on
+ * destinations that are available but have not yet been added locally.
*
* Enumeration happens on the current thread and does not return until all
* destinations have been enumerated or the callback function returns 0.
*
+ * Note: The callback function will likely receive multiple updates for the same
+ * destinations - it is up to the caller to suppress any duplicate destinations.
+ *
* @since CUPS 1.6/macOS 10.8@
*/
int /* O - 1 on success, 0 on failure */
cupsEnumDests(
- unsigned flags, /* I - Enumeration flags */
- int msec, /* I - Timeout in milliseconds,
- * -1 for indefinite */
- int *cancel, /* I - Pointer to "cancel" variable */
- cups_ptype_t type, /* I - Printer type bits */
- cups_ptype_t mask, /* I - Mask for printer type bits */
- cups_dest_cb_t cb, /* I - Callback function */
- void *user_data) /* I - User data */
+ unsigned flags, /* I - Enumeration flags */
+ int msec, /* I - Timeout in milliseconds, -1 for indefinite */
+ int *cancel, /* I - Pointer to "cancel" variable */
+ cups_ptype_t type, /* I - Printer type bits */
+ cups_ptype_t mask, /* I - Mask for printer type bits */
+ cups_dest_cb_t cb, /* I - Callback function */
+ void *user_data) /* I - User data */
{
- int i, /* Looping var */
- num_dests; /* Number of destinations */
- cups_dest_t *dests = NULL, /* Destinations */
- *dest; /* Current destination */
- const char *defprinter; /* Default printer */
- char name[1024], /* Copy of printer name */
- *instance, /* Pointer to instance name */
- *user_default; /* User default printer */
-#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
- int count, /* Number of queries started */
- remaining; /* Remainder of timeout */
- _cups_dnssd_data_t data; /* Data for callback */
- _cups_dnssd_device_t *device; /* Current device */
-# ifdef HAVE_DNSSD
- int nfds, /* Number of files responded */
- main_fd; /* File descriptor for lookups */
- DNSServiceRef ipp_ref, /* IPP browser */
- local_ipp_ref; /* Local IPP browser */
-# ifdef HAVE_SSL
- DNSServiceRef ipps_ref, /* IPPS browser */
- local_ipps_ref; /* Local IPPS browser */
-# endif /* HAVE_SSL */
-# ifdef HAVE_POLL
- struct pollfd pfd; /* Polling data */
-# else
- fd_set input; /* Input set for select() */
- struct timeval timeout; /* Timeout for select() */
-# endif /* HAVE_POLL */
-# else /* HAVE_AVAHI */
- int error; /* Error value */
- AvahiServiceBrowser *ipp_ref; /* IPP browser */
-# ifdef HAVE_SSL
- AvahiServiceBrowser *ipps_ref; /* IPPS browser */
-# endif /* HAVE_SSL */
-# endif /* HAVE_DNSSD */
-#endif /* HAVE_DNSSD || HAVE_AVAHI */
-
- /*
- * Range check input...
- */
-
- (void)flags;
-
- if (!cb)
- return (0);
-
- /*
- * Get the list of local printers and pass them to the callback function...
- */
-
- num_dests = _cupsGetDests(CUPS_HTTP_DEFAULT, IPP_OP_CUPS_GET_PRINTERS, NULL,
- &dests, type, mask | CUPS_PRINTER_3D);
-
- if ((user_default = _cupsUserDefault(name, sizeof(name))) != NULL)
- defprinter = name;
- else if ((defprinter = cupsGetDefault2(CUPS_HTTP_DEFAULT)) != NULL)
- {
- strlcpy(name, defprinter, sizeof(name));
- defprinter = name;
- }
-
- if (defprinter)
- {
- /*
- * Separate printer and instance name...
- */
-
- if ((instance = strchr(name, '/')) != NULL)
- *instance++ = '\0';
-
- /*
- * Lookup the printer and instance and make it the default...
- */
-
- if ((dest = cupsGetDest(name, instance, num_dests, dests)) != NULL)
- dest->is_default = 1;
- }
-
- for (i = num_dests, dest = dests;
- i > 0 && (!cancel || !*cancel);
- i --, dest ++)
- if (!(*cb)(user_data, i > 1 ? CUPS_DEST_FLAGS_MORE : CUPS_DEST_FLAGS_NONE,
- dest))
- break;
-
- cupsFreeDests(num_dests, dests);
-
- if (i > 0 || msec == 0)
- return (1);
-
-#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
- /*
- * Get Bonjour-shared printers...
- */
-
- data.type = type;
- data.mask = mask;
- data.cb = cb;
- data.user_data = user_data;
- data.devices = cupsArrayNew3((cups_array_func_t)cups_dnssd_compare_devices, NULL, NULL, 0, NULL, (cups_afree_func_t)cups_dnssd_free_device);
-
-# ifdef HAVE_DNSSD
- if (DNSServiceCreateConnection(&data.main_ref) != kDNSServiceErr_NoError)
- return (0);
-
- main_fd = DNSServiceRefSockFD(data.main_ref);
-
- ipp_ref = data.main_ref;
- DNSServiceBrowse(&ipp_ref, kDNSServiceFlagsShareConnection, 0,
- "_ipp._tcp", NULL,
- (DNSServiceBrowseReply)cups_dnssd_browse_cb, &data);
-
- local_ipp_ref = data.main_ref;
- DNSServiceBrowse(&local_ipp_ref, kDNSServiceFlagsShareConnection,
- kDNSServiceInterfaceIndexLocalOnly,
- "_ipp._tcp", NULL,
- (DNSServiceBrowseReply)cups_dnssd_local_cb, &data);
-
-# ifdef HAVE_SSL
- ipps_ref = data.main_ref;
- DNSServiceBrowse(&ipps_ref, kDNSServiceFlagsShareConnection, 0,
- "_ipps._tcp", NULL,
- (DNSServiceBrowseReply)cups_dnssd_browse_cb, &data);
-
- local_ipps_ref = data.main_ref;
- DNSServiceBrowse(&local_ipps_ref, kDNSServiceFlagsShareConnection,
- kDNSServiceInterfaceIndexLocalOnly,
- "_ipps._tcp", NULL,
- (DNSServiceBrowseReply)cups_dnssd_local_cb, &data);
-# endif /* HAVE_SSL */
-
-# else /* HAVE_AVAHI */
- if ((data.simple_poll = avahi_simple_poll_new()) == NULL)
- {
- DEBUG_puts("cupsEnumDests: Unable to create Avahi simple poll object.");
- return (1);
- }
-
- avahi_simple_poll_set_func(data.simple_poll, cups_dnssd_poll_cb, &data);
-
- data.client = avahi_client_new(avahi_simple_poll_get(data.simple_poll),
- 0, cups_dnssd_client_cb, &data,
- &error);
- if (!data.client)
- {
- DEBUG_puts("cupsEnumDests: Unable to create Avahi client.");
- avahi_simple_poll_free(data.simple_poll);
- return (1);
- }
-
- ipp_ref = avahi_service_browser_new(data.client, AVAHI_IF_UNSPEC,
- AVAHI_PROTO_UNSPEC, "_ipp._tcp", NULL,
- 0, cups_dnssd_browse_cb, &data);
-# ifdef HAVE_SSL
- ipps_ref = avahi_service_browser_new(data.client, AVAHI_IF_UNSPEC,
- AVAHI_PROTO_UNSPEC, "_ipps._tcp", NULL,
- 0, cups_dnssd_browse_cb, &data);
-# endif /* HAVE_SSL */
-# endif /* HAVE_DNSSD */
-
- if (msec < 0)
- remaining = INT_MAX;
- else
- remaining = msec;
-
- while (remaining > 0 && (!cancel || !*cancel))
- {
- /*
- * Check for input...
- */
-
-# ifdef HAVE_DNSSD
-# ifdef HAVE_POLL
- pfd.fd = main_fd;
- pfd.events = POLLIN;
-
- nfds = poll(&pfd, 1, remaining > 250 ? 250 : remaining);
-
-# else
- FD_ZERO(&input);
- FD_SET(main_fd, &input);
-
- timeout.tv_sec = 0;
- timeout.tv_usec = remaining > 250 ? 250000 : remaining * 1000;
-
- nfds = select(main_fd + 1, &input, NULL, NULL, &timeout);
-# endif /* HAVE_POLL */
-
- if (nfds > 0)
- DNSServiceProcessResult(data.main_ref);
- else if (nfds == 0)
- remaining -= 250;
-
-# else /* HAVE_AVAHI */
- data.got_data = 0;
-
- if ((error = avahi_simple_poll_iterate(data.simple_poll, 250)) > 0)
- {
- /*
- * We've been told to exit the loop. Perhaps the connection to
- * Avahi failed.
- */
-
- break;
- }
-
- if (!data.got_data)
- remaining -= 250;
-# endif /* HAVE_DNSSD */
-
- for (device = (_cups_dnssd_device_t *)cupsArrayFirst(data.devices),
- count = 0;
- device;
- device = (_cups_dnssd_device_t *)cupsArrayNext(data.devices))
- {
- if (device->ref)
- count ++;
-
- if (!device->ref && device->state == _CUPS_DNSSD_NEW)
- {
- DEBUG_printf(("1cupsEnumDests: Querying '%s'.", device->fullName));
-
-# ifdef HAVE_DNSSD
- device->ref = data.main_ref;
-
- if (DNSServiceQueryRecord(&(device->ref),
- kDNSServiceFlagsShareConnection,
- 0, device->fullName,
- kDNSServiceType_TXT,
- kDNSServiceClass_IN,
- (DNSServiceQueryRecordReply)cups_dnssd_query_cb,
- &data) == kDNSServiceErr_NoError)
- {
- count ++;
- }
- else
- {
- device->ref = 0;
- device->state = _CUPS_DNSSD_ERROR;
-
- DEBUG_puts("1cupsEnumDests: Query failed.");
- }
-
-# else /* HAVE_AVAHI */
- if ((device->ref = avahi_record_browser_new(data.client,
- AVAHI_IF_UNSPEC,
- AVAHI_PROTO_UNSPEC,
- device->fullName,
- AVAHI_DNS_CLASS_IN,
- AVAHI_DNS_TYPE_TXT,
- 0,
- cups_dnssd_query_cb,
- &data)) != NULL)
- {
- count ++;
- }
- else
- {
- device->state = _CUPS_DNSSD_ERROR;
-
- DEBUG_printf(("1cupsEnumDests: Query failed: %s",
- avahi_strerror(avahi_client_errno(data.client))));
- }
-# endif /* HAVE_DNSSD */
- }
- else if (device->ref && device->state == _CUPS_DNSSD_PENDING)
- {
- if ((device->type & mask) == type)
- {
- if (!(*cb)(user_data, CUPS_DEST_FLAGS_NONE, &device->dest))
- {
- remaining = -1;
- break;
- }
- }
-
- device->state = _CUPS_DNSSD_ACTIVE;
- }
- }
- }
-
- cupsArrayDelete(data.devices);
-
-# ifdef HAVE_DNSSD
- DNSServiceRefDeallocate(ipp_ref);
- DNSServiceRefDeallocate(local_ipp_ref);
-
-# ifdef HAVE_SSL
- DNSServiceRefDeallocate(ipp_ref);
- DNSServiceRefDeallocate(local_ipp_ref);
-# endif /* HAVE_SSL */
-
- DNSServiceRefDeallocate(data.main_ref);
-
-# else /* HAVE_AVAHI */
- avahi_service_browser_free(ipp_ref);
-# ifdef HAVE_SSL
- avahi_service_browser_free(ipps_ref);
-# endif /* HAVE_SSL */
-
- avahi_client_free(data.client);
- avahi_simple_poll_free(data.simple_poll);
-# endif /* HAVE_DNSSD */
-#endif /* HAVE_DNSSD || HAVE_DNSSD */
-
- return (1);
+ return (cups_enum_dests(CUPS_HTTP_DEFAULT, flags, msec, cancel, type, mask, cb, user_data));
}
@@ -1242,15 +987,23 @@ cupsEnumDests(
/*
* 'cupsEnumDestsBlock()' - Enumerate available destinations with a block.
*
- * Destinations are enumerated from one or more sources. The block receives the
- * destination name, instance, number of options, and options which can be used
- * as input to the @link cupsAddDest@ function. The block must return 1 to
+ * Destinations are enumerated from one or more sources. The block receives the
+ * @code user_data@ pointer and the destination pointer which can be used as
+ * input to the @link cupsCopyDest@ function. The block must return 1 to
* continue enumeration or 0 to stop.
*
+ * The @code type@ and @code mask@ arguments allow the caller to filter the
+ * destinations that are enumerated. Passing 0 for both will enumerate all
+ * printers. The constant @code CUPS_PRINTER_DISCOVERED@ is used to filter on
+ * destinations that are available but have not yet been added locally.
+ *
* Enumeration happens on the current thread and does not return until all
* destinations have been enumerated or the block returns 0.
*
- * @since CUPS 1.6/macOS 10.8@
+ * Note: The block will likely receive multiple updates for the same
+ * destinations - it is up to the caller to suppress any duplicate destinations.
+ *
+ * @since CUPS 1.6/macOS 10.8@ @exclude all@
*/
int /* O - 1 on success, 0 on failure */
@@ -1298,7 +1051,7 @@ cupsFreeDests(int num_dests, /* I - Number of destinations */
/*
* 'cupsGetDest()' - Get the named destination from the list.
*
- * Use the @link cupsGetDests@ or @link cupsGetDests2@ functions to get a
+ * Use the @link cupsEnumDests@ or @link cupsGetDests2@ functions to get a
* list of supported destinations for the current user.
*/
@@ -1363,6 +1116,8 @@ _cupsGetDestResource(
int port; /* Port number */
+ DEBUG_printf(("_cupsGetDestResource(dest=%p(%s), resource=%p, resourcesize=%d)", (void *)dest, dest->name, (void *)resource, (int)resourcesize));
+
/*
* Range check input...
*/
@@ -1380,34 +1135,59 @@ _cupsGetDestResource(
* Grab the printer URI...
*/
- if ((uri = cupsGetOption("printer-uri-supported", dest->num_options,
- dest->options)) == NULL)
+ if ((uri = cupsGetOption("printer-uri-supported", dest->num_options, dest->options)) == NULL)
{
- if (resource)
- *resource = '\0';
+ if ((uri = cupsGetOption("device-uri", dest->num_options, dest->options)) != NULL)
+ {
+#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
+ if (strstr(uri, "._tcp"))
+ uri = cups_dnssd_resolve(dest, uri, 5000, NULL, NULL, NULL);
+#endif /* HAVE_DNSSD || HAVE_AVAHI */
+ }
- _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(ENOENT), 0);
+ if (uri)
+ {
+ DEBUG_printf(("1_cupsGetDestResource: Resolved printer-uri-supported=\"%s\"", uri));
- return (NULL);
- }
+ uri = _cupsCreateDest(dest->name, cupsGetOption("printer-info", dest->num_options, dest->options), NULL, uri, resource, resourcesize);
+ }
+
+ if (uri)
+ {
+ DEBUG_printf(("1_cupsGetDestResource: Local printer-uri-supported=\"%s\"", uri));
+
+ dest->num_options = cupsAddOption("printer-uri-supported", uri, dest->num_options, &dest->options);
+
+ uri = cupsGetOption("printer-uri-supported", dest->num_options, dest->options);
+ }
+ else
+ {
+ DEBUG_puts("1_cupsGetDestResource: No printer-uri-supported found.");
+
+ if (resource)
+ *resource = '\0';
+
+ _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(ENOENT), 0);
-#ifdef HAVE_DNSSD
- if (strstr(uri, "._tcp"))
- {
- if ((uri = cups_dnssd_resolve(dest, uri, 5000, NULL, NULL, NULL)) == NULL)
return (NULL);
+ }
}
-#endif /* HAVE_DNSSD */
-
- if (httpSeparateURI(HTTP_URI_CODING_ALL, uri, scheme, sizeof(scheme),
- userpass, sizeof(userpass), hostname, sizeof(hostname),
- &port, resource, (int)resourcesize) < HTTP_URI_STATUS_OK)
+ else
{
- _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Bad printer-uri."), 1);
+ DEBUG_printf(("1_cupsGetDestResource: printer-uri-supported=\"%s\"", uri));
- return (NULL);
+ if (httpSeparateURI(HTTP_URI_CODING_ALL, uri, scheme, sizeof(scheme),
+ userpass, sizeof(userpass), hostname, sizeof(hostname),
+ &port, resource, (int)resourcesize) < HTTP_URI_STATUS_OK)
+ {
+ _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Bad printer-uri."), 1);
+
+ return (NULL);
+ }
}
+ DEBUG_printf(("1_cupsGetDestResource: resource=\"%s\"", resource));
+
return (uri);
}
@@ -1434,6 +1214,7 @@ cupsGetDestWithURI(const char *name, /* I - Desired printer name or @code NULL@
hostname[256], /* Hostname from URI */
resource[1024], /* Resource path from URI */
*ptr; /* Pointer into string */
+ const char *info; /* printer-info string */
int port; /* Port number from URI */
@@ -1455,7 +1236,11 @@ cupsGetDestWithURI(const char *name, /* I - Desired printer name or @code NULL@
return (NULL);
}
- if (!name)
+ if (name)
+ {
+ info = name;
+ }
+ else
{
/*
* Create the name from the URI...
@@ -1467,24 +1252,29 @@ cupsGetDestWithURI(const char *name, /* I - Desired printer name or @code NULL@
* Use the service instance name...
*/
- if ((ptr = strchr(hostname, '.')) != NULL)
+ if ((ptr = strstr(hostname, "._")) != NULL)
*ptr = '\0';
- name = hostname;
+ cups_queue_name(temp, hostname, sizeof(temp));
+ name = temp;
+ info = hostname;
}
else if (!strncmp(resource, "/classes/", 9))
{
snprintf(temp, sizeof(temp), "%s @ %s", resource + 9, hostname);
- name = temp;
+ name = resource + 9;
+ info = temp;
}
else if (!strncmp(resource, "/printers/", 10))
{
snprintf(temp, sizeof(temp), "%s @ %s", resource + 10, hostname);
- name = temp;
+ name = resource + 10;
+ info = temp;
}
else
{
name = hostname;
+ info = hostname;
}
}
@@ -1500,7 +1290,7 @@ cupsGetDestWithURI(const char *name, /* I - Desired printer name or @code NULL@
dest->name = _cupsStrAlloc(name);
dest->num_options = cupsAddOption("device-uri", uri, dest->num_options, &(dest->options));
- dest->num_options = cupsAddOption("printer-info", name, dest->num_options, &(dest->options));
+ dest->num_options = cupsAddOption("printer-info", info, dest->num_options, &(dest->options));
return (dest);
}
@@ -1574,6 +1364,7 @@ _cupsGetDests(http_t *http, /* I - Connection to server or
"printer-info",
"printer-is-accepting-jobs",
"printer-is-shared",
+ "printer-is-temporary",
"printer-location",
"printer-make-and-model",
"printer-mandatory-job-attributes",
@@ -1586,12 +1377,15 @@ _cupsGetDests(http_t *http, /* I - Connection to server or
};
+ DEBUG_printf(("_cupsGetDests(http=%p, op=%x(%s), name=\"%s\", dests=%p, type=%x, mask=%x)", (void *)http, op, ippOpString(op), name, (void *)dests, type, mask));
+
#ifdef __APPLE__
/*
* Get the default paper size...
*/
appleGetPaperSize(media_default, sizeof(media_default));
+ DEBUG_printf(("1_cupsGetDests: Default media is '%s'.", media_default));
#endif /* __APPLE__ */
/*
@@ -1678,7 +1472,8 @@ _cupsGetDests(http_t *http, /* I - Connection to server or
!strcmp(attr->name, "marker-types") ||
!strcmp(attr->name, "printer-commands") ||
!strcmp(attr->name, "printer-info") ||
- !strcmp(attr->name, "printer-is-shared") ||
+ !strcmp(attr->name, "printer-is-shared") ||
+ !strcmp(attr->name, "printer-is-temporary") ||
!strcmp(attr->name, "printer-make-and-model") ||
!strcmp(attr->name, "printer-mandatory-job-attributes") ||
!strcmp(attr->name, "printer-state") ||
@@ -1699,7 +1494,7 @@ _cupsGetDests(http_t *http, /* I - Connection to server or
num_options, &options);
}
#ifdef __APPLE__
- else if (!strcmp(attr->name, "media-supported"))
+ else if (!strcmp(attr->name, "media-supported") && media_default[0])
{
/*
* See if we can set a default media size...
@@ -1710,8 +1505,8 @@ _cupsGetDests(http_t *http, /* I - Connection to server or
for (i = 0; i < attr->num_values; i ++)
if (!_cups_strcasecmp(media_default, attr->values[i].string.text))
{
- num_options = cupsAddOption("media", media_default, num_options,
- &options);
+ DEBUG_printf(("1_cupsGetDests: Setting media to '%s'.", media_default));
+ num_options = cupsAddOption("media", media_default, num_options, &options);
break;
}
}
@@ -1720,7 +1515,8 @@ _cupsGetDests(http_t *http, /* I - Connection to server or
attr->value_tag == IPP_TAG_NAME)
printer_name = attr->values[0].string.text;
else if (strncmp(attr->name, "notify-", 7) &&
- (attr->value_tag == IPP_TAG_BOOLEAN ||
+ strncmp(attr->name, "print-quality-", 14) &&
+ (attr->value_tag == IPP_TAG_BOOLEAN ||
attr->value_tag == IPP_TAG_ENUM ||
attr->value_tag == IPP_TAG_INTEGER ||
attr->value_tag == IPP_TAG_KEYWORD ||
@@ -1735,12 +1531,8 @@ _cupsGetDests(http_t *http, /* I - Connection to server or
strlcpy(optname, attr->name, sizeof(optname));
optname[ptr - attr->name] = '\0';
- if (_cups_strcasecmp(optname, "media") ||
- !cupsGetOption("media", num_options, options))
- num_options = cupsAddOption(optname,
- cups_make_string(attr, value,
- sizeof(value)),
- num_options, &options);
+ if (_cups_strcasecmp(optname, "media") || !cupsGetOption("media", num_options, options))
+ num_options = cupsAddOption(optname, cups_make_string(attr, value, sizeof(value)), num_options, &options);
}
}
@@ -1785,15 +1577,23 @@ _cupsGetDests(http_t *http, /* I - Connection to server or
* 'cupsGetDests()' - Get the list of destinations from the default server.
*
* Starting with CUPS 1.2, the returned list of destinations include the
- * printer-info, printer-is-accepting-jobs, printer-is-shared,
- * printer-make-and-model, printer-state, printer-state-change-time,
- * printer-state-reasons, and printer-type attributes as options. CUPS 1.4
- * adds the marker-change-time, marker-colors, marker-high-levels,
- * marker-levels, marker-low-levels, marker-message, marker-names,
- * marker-types, and printer-commands attributes as well.
+ * "printer-info", "printer-is-accepting-jobs", "printer-is-shared",
+ * "printer-make-and-model", "printer-state", "printer-state-change-time",
+ * "printer-state-reasons", "printer-type", and "printer-uri-supported"
+ * attributes as options.
+ *
+ * CUPS 1.4 adds the "marker-change-time", "marker-colors",
+ * "marker-high-levels", "marker-levels", "marker-low-levels", "marker-message",
+ * "marker-names", "marker-types", and "printer-commands" attributes as options.
+ *
+ * CUPS 2.2 adds accessible IPP printers to the list of destinations that can
+ * be used. The "printer-uri-supported" option will be present for those IPP
+ * printers that have been recently used.
*
* Use the @link cupsFreeDests@ function to free the destination list and
* the @link cupsGetDest@ function to find a particular destination.
+ *
+ * @exclude all@
*/
int /* O - Number of destinations */
@@ -1807,12 +1607,18 @@ cupsGetDests(cups_dest_t **dests) /* O - Destinations */
* 'cupsGetDests2()' - Get the list of destinations from the specified server.
*
* Starting with CUPS 1.2, the returned list of destinations include the
- * printer-info, printer-is-accepting-jobs, printer-is-shared,
- * printer-make-and-model, printer-state, printer-state-change-time,
- * printer-state-reasons, and printer-type attributes as options. CUPS 1.4
- * adds the marker-change-time, marker-colors, marker-high-levels,
- * marker-levels, marker-low-levels, marker-message, marker-names,
- * marker-types, and printer-commands attributes as well.
+ * "printer-info", "printer-is-accepting-jobs", "printer-is-shared",
+ * "printer-make-and-model", "printer-state", "printer-state-change-time",
+ * "printer-state-reasons", "printer-type", and "printer-uri-supported"
+ * attributes as options.
+ *
+ * CUPS 1.4 adds the "marker-change-time", "marker-colors",
+ * "marker-high-levels", "marker-levels", "marker-low-levels", "marker-message",
+ * "marker-names", "marker-types", and "printer-commands" attributes as options.
+ *
+ * CUPS 2.2 adds accessible IPP printers to the list of destinations that can
+ * be used. The "printer-uri-supported" option will be present for those IPP
+ * printers that have been recently used.
*
* Use the @link cupsFreeDests@ function to free the destination list and
* the @link cupsGetDest@ function to find a particular destination.
@@ -1824,8 +1630,8 @@ int /* O - Number of destinations */
cupsGetDests2(http_t *http, /* I - Connection to server or @code CUPS_HTTP_DEFAULT@ */
cups_dest_t **dests) /* O - Destinations */
{
- int num_dests; /* Number of destinations */
- cups_dest_t *dest; /* Destination pointer */
+ _cups_getdata_t data; /* Enumeration data */
+ cups_dest_t *dest; /* Current destination */
const char *home; /* HOME environment variable */
char filename[1024]; /* Local ~/.cups/lpoptions file */
const char *defprinter; /* Default printer */
@@ -1837,41 +1643,70 @@ cupsGetDests2(http_t *http, /* I - Connection to server or @code CUPS_HTTP_
_cups_globals_t *cg = _cupsGlobals(); /* Pointer to library globals */
- /*
+ DEBUG_printf(("cupsGetDests2(http=%p, dests=%p)", (void *)http, (void *)dests));
+
+/*
* Range check the input...
*/
if (!dests)
{
_cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Bad NULL dests pointer"), 1);
+ DEBUG_puts("1cupsGetDests2: NULL dests pointer, returning 0.");
return (0);
}
/*
+ * Connect to the server as needed...
+ */
+
+ if (!http)
+ {
+ if ((http = _cupsConnect()) == NULL)
+ {
+ *dests = NULL;
+
+ return (0);
+ }
+ }
+
+ /*
* Grab the printers and classes...
*/
- *dests = (cups_dest_t *)0;
- num_dests = _cupsGetDests(http, IPP_OP_CUPS_GET_PRINTERS, NULL, dests, 0, CUPS_PRINTER_3D);
+ data.num_dests = 0;
+ data.dests = NULL;
- if (cupsLastError() >= IPP_STATUS_REDIRECTION_OTHER_SITE)
+ if (!httpAddrLocalhost(httpGetAddress(http)))
{
- cupsFreeDests(num_dests, *dests);
- *dests = (cups_dest_t *)0;
- return (0);
+ /*
+ * When talking to a remote cupsd, just enumerate printers on the remote
+ * cupsd.
+ */
+
+ cups_enum_dests(http, 0, _CUPS_DNSSD_GET_DESTS, NULL, 0, CUPS_PRINTER_DISCOVERED, (cups_dest_cb_t)cups_get_cb, &data);
+ }
+ else
+ {
+ /*
+ * When talking to a local cupsd, enumerate both local printers and ones we
+ * can find on the network...
+ */
+
+ cups_enum_dests(http, 0, _CUPS_DNSSD_GET_DESTS, NULL, 0, 0, (cups_dest_cb_t)cups_get_cb, &data);
}
/*
* Make a copy of the "real" queues for a later sanity check...
*/
- if (num_dests > 0)
+ if (data.num_dests > 0)
{
- num_reals = num_dests;
+ num_reals = data.num_dests;
reals = calloc((size_t)num_reals, sizeof(cups_dest_t));
if (reals)
- memcpy(reals, *dests, (size_t)num_reals * sizeof(cups_dest_t));
+ memcpy(reals, data.dests, (size_t)num_reals * sizeof(cups_dest_t));
else
num_reals = 0;
}
@@ -1906,7 +1741,7 @@ cupsGetDests2(http_t *http, /* I - Connection to server or @code CUPS_HTTP_
* Lookup the printer and instance and make it the default...
*/
- if ((dest = cupsGetDest(name, instance, num_dests, *dests)) != NULL)
+ if ((dest = cupsGetDest(name, instance, data.num_dests, data.dests)) != NULL)
dest->is_default = 1;
}
else
@@ -1917,15 +1752,13 @@ cupsGetDests2(http_t *http, /* I - Connection to server or @code CUPS_HTTP_
*/
snprintf(filename, sizeof(filename), "%s/lpoptions", cg->cups_serverroot);
- num_dests = cups_get_dests(filename, NULL, NULL, user_default != NULL,
- num_dests, dests);
+ data.num_dests = cups_get_dests(filename, NULL, NULL, user_default != NULL, data.num_dests, &data.dests);
if ((home = getenv("HOME")) != NULL)
{
snprintf(filename, sizeof(filename), "%s/.cups/lpoptions", home);
- num_dests = cups_get_dests(filename, NULL, NULL, user_default != NULL,
- num_dests, dests);
+ data.num_dests = cups_get_dests(filename, NULL, NULL, user_default != NULL, data.num_dests, &data.dests);
}
/*
@@ -1940,7 +1773,7 @@ cupsGetDests2(http_t *http, /* I - Connection to server or @code CUPS_HTTP_
* See if we have a default printer...
*/
- if ((dest = cupsGetDest(NULL, NULL, num_dests, *dests)) != NULL)
+ if ((dest = cupsGetDest(NULL, NULL, data.num_dests, data.dests)) != NULL)
{
/*
* Have a default; see if it is real...
@@ -1953,8 +1786,7 @@ cupsGetDests2(http_t *http, /* I - Connection to server or @code CUPS_HTTP_
* going to an unexpected printer... (<rdar://problem/14216472>)
*/
- num_dests = cupsRemoveDest(dest->name, dest->instance, num_dests,
- dests);
+ data.num_dests = cupsRemoveDest(dest->name, dest->instance, data.num_dests, &data.dests);
}
}
@@ -1969,10 +1801,14 @@ cupsGetDests2(http_t *http, /* I - Connection to server or @code CUPS_HTTP_
* Return the number of destinations...
*/
- if (num_dests > 0)
+ *dests = data.dests;
+
+ if (data.num_dests > 0)
_cupsSetError(IPP_STATUS_OK, NULL, 0);
- return (num_dests);
+ DEBUG_printf(("1cupsGetDests2: Returning %d destinations.", data.num_dests));
+
+ return (data.num_dests);
}
@@ -1980,10 +1816,10 @@ cupsGetDests2(http_t *http, /* I - Connection to server or @code CUPS_HTTP_
* 'cupsGetNamedDest()' - Get options for the named destination.
*
* This function is optimized for retrieving a single destination and should
- * be used instead of @link cupsGetDests@ and @link cupsGetDest@ when you either
- * know the name of the destination or want to print to the default destination.
- * If @code NULL@ is returned, the destination does not exist or there is no
- * default destination.
+ * be used instead of @link cupsGetDests2@ and @link cupsGetDest@ when you
+ * either know the name of the destination or want to print to the default
+ * destination. If @code NULL@ is returned, the destination does not exist or
+ * there is no default destination.
*
* If "http" is @code CUPS_HTTP_DEFAULT@, the connection to the default print
* server will be used.
@@ -2002,6 +1838,7 @@ cupsGetNamedDest(http_t *http, /* I - Connection to server or @code CUPS_HTT
const char *name, /* I - Destination name or @code NULL@ for the default destination */
const char *instance) /* I - Instance name or @code NULL@ */
{
+ const char *dest_name; /* Working destination name */
cups_dest_t *dest; /* Destination */
char filename[1024], /* Path to lpoptions */
defname[256]; /* Default printer name */
@@ -2012,16 +1849,20 @@ cupsGetNamedDest(http_t *http, /* I - Connection to server or @code CUPS_HTT
_cups_globals_t *cg = _cupsGlobals(); /* Pointer to library globals */
+ DEBUG_printf(("cupsGetNamedDest(http=%p, name=\"%s\", instance=\"%s\")", (void *)http, name, instance));
+
/*
* If "name" is NULL, find the default destination...
*/
- if (!name)
+ dest_name = name;
+
+ if (!dest_name)
{
set_as_default = 1;
- name = _cupsUserDefault(defname, sizeof(defname));
+ dest_name = _cupsUserDefault(defname, sizeof(defname));
- if (name)
+ if (dest_name)
{
char *ptr; /* Temporary pointer... */
@@ -2041,36 +1882,60 @@ cupsGetNamedDest(http_t *http, /* I - Connection to server or @code CUPS_HTT
snprintf(filename, sizeof(filename), "%s/.cups/lpoptions", home);
- name = cups_get_default(filename, defname, sizeof(defname), &instance);
+ dest_name = cups_get_default(filename, defname, sizeof(defname), &instance);
}
- if (!name)
+ if (!dest_name)
{
/*
* Still not there? Try the system lpoptions file...
*/
- snprintf(filename, sizeof(filename), "%s/lpoptions",
- cg->cups_serverroot);
- name = cups_get_default(filename, defname, sizeof(defname), &instance);
+ snprintf(filename, sizeof(filename), "%s/lpoptions", cg->cups_serverroot);
+ dest_name = cups_get_default(filename, defname, sizeof(defname), &instance);
}
- if (!name)
+ if (!dest_name)
{
/*
* No locally-set default destination, ask the server...
*/
op = IPP_OP_CUPS_GET_DEFAULT;
+
+ DEBUG_puts("1cupsGetNamedDest: Asking server for default printer...");
}
+ else
+ DEBUG_printf(("1cupsGetNamedDest: Using name=\"%s\"...", name));
}
/*
* Get the printer's attributes...
*/
- if (!_cupsGetDests(http, op, name, &dest, 0, CUPS_PRINTER_3D))
- return (NULL);
+ if (!_cupsGetDests(http, op, dest_name, &dest, 0, 0))
+ {
+ if (name)
+ {
+ _cups_namedata_t data; /* Callback data */
+
+ DEBUG_puts("1cupsGetNamedDest: No queue found for printer, looking on network...");
+
+ data.name = name;
+ data.dest = NULL;
+
+ cupsEnumDests(0, 1000, NULL, 0, 0, (cups_dest_cb_t)cups_name_cb, &data);
+
+ if (!data.dest)
+ return (NULL);
+
+ dest = data.dest;
+ }
+ else
+ return (NULL);
+ }
+
+ DEBUG_printf(("1cupsGetNamedDest: Got dest=%p", (void *)dest));
if (instance)
dest->instance = _cupsStrAlloc(instance);
@@ -2083,13 +1948,13 @@ cupsGetNamedDest(http_t *http, /* I - Connection to server or @code CUPS_HTT
*/
snprintf(filename, sizeof(filename), "%s/lpoptions", cg->cups_serverroot);
- cups_get_dests(filename, name, instance, 1, 1, &dest);
+ cups_get_dests(filename, dest_name, instance, 1, 1, &dest);
if (home)
{
snprintf(filename, sizeof(filename), "%s/.cups/lpoptions", home);
- cups_get_dests(filename, name, instance, 1, 1, &dest);
+ cups_get_dests(filename, dest_name, instance, 1, 1, &dest);
}
/*
@@ -2193,6 +2058,8 @@ cupsSetDefaultDest(
*
* This function saves the destinations to /etc/cups/lpoptions when run
* as root and ~/.cups/lpoptions when run as a normal user.
+ *
+ * @exclude all@
*/
void
@@ -2245,7 +2112,7 @@ cupsSetDests2(http_t *http, /* I - Connection to server or @code CUPS_HTTP_
* Get the server destinations...
*/
- num_temps = _cupsGetDests(http, IPP_OP_CUPS_GET_PRINTERS, NULL, &temps, 0, CUPS_PRINTER_3D);
+ num_temps = _cupsGetDests(http, IPP_OP_CUPS_GET_PRINTERS, NULL, &temps, 0, 0);
if (cupsLastError() >= IPP_STATUS_REDIRECTION_OTHER_SITE)
{
@@ -2839,11 +2706,12 @@ cups_dnssd_browse_cb(
(void)protocol;
(void)context;
+ DEBUG_printf(("cups_dnssd_browse_cb(..., name=\"%s\", type=\"%s\", domain=\"%s\", ...);", name, type, domain));
+
switch (event)
{
case AVAHI_BROWSER_FAILURE:
- DEBUG_printf(("cups_dnssd_browse_cb: %s",
- avahi_strerror(avahi_client_errno(client))));
+ DEBUG_printf(("cups_dnssd_browse_cb: %s", avahi_strerror(avahi_client_errno(client))));
avahi_simple_poll_quit(data->simple_poll);
break;
@@ -2858,8 +2726,7 @@ cups_dnssd_browse_cb(
* This comes from the local machine so ignore it.
*/
- DEBUG_printf(("cups_dnssd_browse_cb: Ignoring local service \"%s\".",
- name));
+ DEBUG_printf(("cups_dnssd_browse_cb: Ignoring local service \"%s\".", name));
}
else
{
@@ -2871,9 +2738,13 @@ cups_dnssd_browse_cb(
}
break;
- case AVAHI_BROWSER_REMOVE:
- case AVAHI_BROWSER_ALL_FOR_NOW:
- case AVAHI_BROWSER_CACHE_EXHAUSTED:
+ case AVAHI_BROWSER_REMOVE :
+ case AVAHI_BROWSER_CACHE_EXHAUSTED :
+ break;
+
+ case AVAHI_BROWSER_ALL_FOR_NOW :
+ DEBUG_puts("cups_dnssd_browse_cb: ALL_FOR_NOW");
+ data->browsers --;
break;
}
}
@@ -2895,6 +2766,8 @@ cups_dnssd_client_cb(
(void)client;
+ DEBUG_printf(("cups_dnssd_client_cb(client=%p, state=%d, context=%p)", client, state, context));
+
/*
* If the connection drops, quit.
*/
@@ -2964,8 +2837,9 @@ cups_dnssd_get_device(
{
_cups_dnssd_device_t key, /* Search key */
*device; /* Device */
- char fullName[kDNSServiceMaxDomainName];
+ char fullName[kDNSServiceMaxDomainName],
/* Full name for query */
+ name[128]; /* Queue name */
DEBUG_printf(("5cups_dnssd_get_device(data=%p, serviceName=\"%s\", regtype=\"%s\", replyDomain=\"%s\")", (void *)data, serviceName, regtype, replyDomain));
@@ -2974,7 +2848,9 @@ cups_dnssd_get_device(
* See if this is an existing device...
*/
- key.dest.name = (char *)serviceName;
+ cups_queue_name(name, serviceName, sizeof(name));
+
+ key.dest.name = name;
if ((device = cupsArrayFind(data->devices, &key)) != NULL)
{
@@ -3035,10 +2911,12 @@ cups_dnssd_get_device(
replyDomain));
device = calloc(sizeof(_cups_dnssd_device_t), 1);
- device->dest.name = _cupsStrAlloc(serviceName);
+ device->dest.name = _cupsStrAlloc(name);
device->domain = _cupsStrAlloc(replyDomain);
device->regtype = _cupsStrAlloc(regtype);
+ device->dest.num_options = cupsAddOption("printer-info", serviceName, 0, &device->dest.options);
+
cupsArrayAdd(data->devices, device);
}
@@ -3047,11 +2925,9 @@ cups_dnssd_get_device(
*/
# ifdef HAVE_DNSSD
- DNSServiceConstructFullName(fullName, device->dest.name, device->regtype,
- device->domain);
+ DNSServiceConstructFullName(fullName, serviceName, regtype, replyDomain);
# else /* HAVE_AVAHI */
- avahi_service_name_join(fullName, kDNSServiceMaxDomainName, serviceName,
- regtype, replyDomain);
+ avahi_service_name_join(fullName, kDNSServiceMaxDomainName, serviceName, regtype, replyDomain);
# endif /* HAVE_DNSSD */
_cupsStrFree(device->fullName);
@@ -3070,6 +2946,8 @@ cups_dnssd_get_device(
if (device->state == _CUPS_DNSSD_ACTIVE)
{
+ DEBUG_printf(("6cups_dnssd_get_device: Remove callback for \"%s\".", device->dest.name));
+
(*data->cb)(data->user_data, CUPS_DEST_FLAGS_REMOVED, &device->dest);
device->state = _CUPS_DNSSD_NEW;
}
@@ -3128,7 +3006,10 @@ cups_dnssd_local_cb(
}
if (device->state == _CUPS_DNSSD_ACTIVE)
+ {
+ DEBUG_printf(("6cups_dnssd_local_cb: Remove callback for \"%s\".", device->dest.name));
(*data->cb)(data->user_data, CUPS_DEST_FLAGS_REMOVED, &device->dest);
+ }
device->state = _CUPS_DNSSD_LOCAL;
}
@@ -3141,7 +3022,9 @@ cups_dnssd_local_cb(
*
* Note: This function is needed because avahi_simple_poll_iterate is broken
* and always uses a timeout of 0 (!) milliseconds.
- * (Avahi Ticket #364)
+ * (https://github.com/lathiat/avahi/issues/127)
+ *
+ * @private@
*/
static int /* O - Number of file descriptors matching */
@@ -3156,16 +3039,22 @@ cups_dnssd_poll_cb(
int val; /* Return value */
+ DEBUG_printf(("cups_dnssd_poll_cb(pollfds=%p, num_pollfds=%d, timeout=%d, context=%p)", pollfds, num_pollfds, timeout, context));
+
(void)timeout;
- val = poll(pollfds, num_pollfds, 250);
+ val = poll(pollfds, num_pollfds, _CUPS_DNSSD_MAXTIME);
+
+ DEBUG_printf(("cups_dnssd_poll_cb: poll() returned %d", val));
if (val < 0)
{
DEBUG_printf(("cups_dnssd_poll_cb: %s", strerror(errno)));
}
else if (val > 0)
+ {
data->got_data = 1;
+ }
return (val);
}
@@ -3214,7 +3103,8 @@ cups_dnssd_query_cb(
# endif /* HAVE_DNSSD */
_cups_dnssd_data_t *data = (_cups_dnssd_data_t *)context;
/* Enumeration data */
- char name[1024], /* Service name */
+ char serviceName[256],/* Service name */
+ name[128], /* Queue name */
*ptr; /* Pointer into string */
_cups_dnssd_device_t dkey, /* Search key */
*device; /* Device */
@@ -3231,11 +3121,7 @@ cups_dnssd_query_cb(
return;
# else /* HAVE_AVAHI */
- DEBUG_printf(("5cups_dnssd_query_cb(browser=%p, interfaceIndex=%d, "
- "protocol=%d, event=%d, fullName=\"%s\", rrclass=%u, "
- "rrtype=%u, rdata=%p, rdlen=%u, flags=%x, context=%p)",
- browser, interfaceIndex, protocol, event, fullName, rrclass,
- rrtype, rdata, (unsigned)rdlen, flags, context));
+ DEBUG_printf(("cups_dnssd_query_cb(browser=%p, interfaceIndex=%d, protocol=%d, event=%d, fullName=\"%s\", rrclass=%u, rrtype=%u, rdata=%p, rdlen=%u, flags=%x, context=%p)", browser, interfaceIndex, protocol, event, fullName, rrclass, rrtype, rdata, (unsigned)rdlen, flags, context));
/*
* Only process "add" data...
@@ -3244,8 +3130,7 @@ cups_dnssd_query_cb(
if (event != AVAHI_BROWSER_NEW)
{
if (event == AVAHI_BROWSER_FAILURE)
- DEBUG_printf(("cups_dnssd_query_cb: %s",
- avahi_strerror(avahi_client_errno(client))));
+ DEBUG_printf(("cups_dnssd_query_cb: %s", avahi_strerror(avahi_client_errno(client))));
return;
}
@@ -3255,14 +3140,16 @@ cups_dnssd_query_cb(
* Lookup the service in the devices array.
*/
- dkey.dest.name = name;
-
- cups_dnssd_unquote(name, fullName, sizeof(name));
+ cups_dnssd_unquote(serviceName, fullName, sizeof(serviceName));
- if ((ptr = strstr(name, "._")) != NULL)
+ if ((ptr = strstr(serviceName, "._")) != NULL)
*ptr = '\0';
- if ((device = cupsArrayFind(data->devices, &dkey)) != NULL)
+ cups_queue_name(name, serviceName, sizeof(name));
+
+ dkey.dest.name = name;
+
+ if ((device = cupsArrayFind(data->devices, &dkey)) != NULL && device->state == _CUPS_DNSSD_NEW)
{
/*
* Found it, pull out the make and model from the TXT record and save it...
@@ -3279,7 +3166,7 @@ cups_dnssd_query_cb(
model[256], /* Model */
uriname[1024], /* Name for URI */
uri[1024]; /* Printer URI */
- cups_ptype_t type = CUPS_PRINTER_REMOTE | CUPS_PRINTER_BW;
+ cups_ptype_t type = CUPS_PRINTER_DISCOVERED | CUPS_PRINTER_BW;
/* Printer type */
int saw_printer_type = 0;
/* Did we see a printer-type key? */
@@ -3398,7 +3285,7 @@ cups_dnssd_query_cb(
*/
saw_printer_type = 1;
- type = (cups_ptype_t)strtol(value, NULL, 0);
+ type = (cups_ptype_t)strtol(value, NULL, 0) | CUPS_PRINTER_DISCOVERED;
}
else if (!saw_printer_type)
{
@@ -3454,8 +3341,6 @@ cups_dnssd_query_cb(
* Save the printer-xxx values...
*/
- device->dest.num_options = cupsAddOption("printer-info", name, device->dest.num_options, &device->dest.options);
-
if (make_and_model[0])
{
strlcat(make_and_model, " ", sizeof(make_and_model));
@@ -3543,9 +3428,9 @@ cups_dnssd_resolve(
* Save the resolved URI...
*/
- dest->num_options = cupsAddOption("resolved-device-uri", uri, dest->num_options, &dest->options);
+ dest->num_options = cupsAddOption("device-uri", uri, dest->num_options, &dest->options);
- return (cupsGetOption("resolved-device-uri", dest->num_options, dest->options));
+ return (cupsGetOption("device-uri", dest->num_options, dest->options));
}
@@ -3620,6 +3505,476 @@ cups_dnssd_unquote(char *dst, /* I - Destination buffer */
#endif /* HAVE_DNSSD */
+#if defined(HAVE_AVAHI) || defined(HAVE_DNSSD)
+/*
+ * 'cups_elapsed()' - Return the elapsed time in milliseconds.
+ */
+
+static int /* O - Elapsed time in milliseconds */
+cups_elapsed(struct timeval *t) /* IO - Previous time */
+{
+ int msecs; /* Milliseconds */
+ struct timeval nt; /* New time */
+
+
+ gettimeofday(&nt, NULL);
+
+ msecs = (int)(1000 * (nt.tv_sec - t->tv_sec) + (nt.tv_usec - t->tv_usec) / 1000);
+
+ *t = nt;
+
+ return (msecs);
+}
+#endif /* HAVE_AVAHI || HAVE_DNSSD */
+
+
+/*
+ * 'cups_enum_dests()' - Enumerate destinations from a specific server.
+ */
+
+static int /* O - 1 on success, 0 on failure */
+cups_enum_dests(
+ http_t *http, /* I - Connection to scheduler */
+ unsigned flags, /* I - Enumeration flags */
+ int msec, /* I - Timeout in milliseconds, -1 for indefinite */
+ int *cancel, /* I - Pointer to "cancel" variable */
+ cups_ptype_t type, /* I - Printer type bits */
+ cups_ptype_t mask, /* I - Mask for printer type bits */
+ cups_dest_cb_t cb, /* I - Callback function */
+ void *user_data) /* I - User data */
+{
+ int i, /* Looping var */
+ num_dests; /* Number of destinations */
+ cups_dest_t *dests = NULL, /* Destinations */
+ *dest; /* Current destination */
+ const char *defprinter; /* Default printer */
+ char name[1024], /* Copy of printer name */
+ *instance, /* Pointer to instance name */
+ *user_default; /* User default printer */
+#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
+ int count, /* Number of queries started */
+ completed, /* Number of completed queries */
+ remaining; /* Remainder of timeout */
+ struct timeval curtime; /* Current time */
+ _cups_dnssd_data_t data; /* Data for callback */
+ _cups_dnssd_device_t *device; /* Current device */
+# ifdef HAVE_DNSSD
+ int nfds, /* Number of files responded */
+ main_fd; /* File descriptor for lookups */
+ DNSServiceRef ipp_ref = NULL, /* IPP browser */
+ local_ipp_ref = NULL; /* Local IPP browser */
+# ifdef HAVE_SSL
+ DNSServiceRef ipps_ref = NULL, /* IPPS browser */
+ local_ipps_ref = NULL; /* Local IPPS browser */
+# endif /* HAVE_SSL */
+# ifdef HAVE_POLL
+ struct pollfd pfd; /* Polling data */
+# else
+ fd_set input; /* Input set for select() */
+ struct timeval timeout; /* Timeout for select() */
+# endif /* HAVE_POLL */
+# else /* HAVE_AVAHI */
+ int error; /* Error value */
+ AvahiServiceBrowser *ipp_ref = NULL; /* IPP browser */
+# ifdef HAVE_SSL
+ AvahiServiceBrowser *ipps_ref = NULL; /* IPPS browser */
+# endif /* HAVE_SSL */
+# endif /* HAVE_DNSSD */
+#endif /* HAVE_DNSSD || HAVE_AVAHI */
+
+
+ DEBUG_printf(("cups_enum_dests(flags=%x, msec=%d, cancel=%p, type=%x, mask=%x, cb=%p, user_data=%p)", flags, msec, (void *)cancel, type, mask, (void *)cb, (void *)user_data));
+
+ /*
+ * Range check input...
+ */
+
+ (void)flags;
+
+ if (!cb)
+ {
+ DEBUG_puts("1cups_enum_dests: No callback, returning 0.");
+ return (0);
+ }
+
+ /*
+ * Get ready to enumerate...
+ */
+
+#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
+ memset(&data, 0, sizeof(data));
+
+ data.type = type;
+ data.mask = mask;
+ data.cb = cb;
+ data.user_data = user_data;
+ data.devices = cupsArrayNew3((cups_array_func_t)cups_dnssd_compare_devices, NULL, NULL, 0, NULL, (cups_afree_func_t)cups_dnssd_free_device);
+#endif /* HAVE_DNSSD || HAVE_AVAHI */
+
+ if (!(mask & CUPS_PRINTER_DISCOVERED) || !(type & CUPS_PRINTER_DISCOVERED))
+ {
+ /*
+ * Get the list of local printers and pass them to the callback function...
+ */
+
+ num_dests = _cupsGetDests(http, IPP_OP_CUPS_GET_PRINTERS, NULL, &dests, type, mask);
+
+ if ((user_default = _cupsUserDefault(name, sizeof(name))) != NULL)
+ defprinter = name;
+ else if ((defprinter = cupsGetDefault2(http)) != NULL)
+ {
+ strlcpy(name, defprinter, sizeof(name));
+ defprinter = name;
+ }
+
+ if (defprinter)
+ {
+ /*
+ * Separate printer and instance name...
+ */
+
+ if ((instance = strchr(name, '/')) != NULL)
+ *instance++ = '\0';
+
+ /*
+ * Lookup the printer and instance and make it the default...
+ */
+
+ if ((dest = cupsGetDest(name, instance, num_dests, dests)) != NULL)
+ dest->is_default = 1;
+ }
+
+ for (i = num_dests, dest = dests;
+ i > 0 && (!cancel || !*cancel);
+ i --, dest ++)
+ {
+#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
+ const char *device_uri; /* Device URI */
+#endif /* HAVE_DNSSD || HAVE_AVAHI */
+
+ if (!(*cb)(user_data, i > 1 ? CUPS_DEST_FLAGS_MORE : CUPS_DEST_FLAGS_NONE, dest))
+ break;
+
+#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
+ if (!dest->instance && (device_uri = cupsGetOption("device-uri", dest->num_options, dest->options)) != NULL && !strncmp(device_uri, "dnssd://", 8))
+ {
+ /*
+ * Add existing queue using service name, etc. so we don't list it again...
+ */
+
+ char scheme[32], /* URI scheme */
+ userpass[32], /* Username:password */
+ serviceName[256], /* Service name (host field) */
+ resource[256], /* Resource (options) */
+ *regtype, /* Registration type */
+ *replyDomain; /* Registration domain */
+ int port; /* Port number (not used) */
+
+ if (httpSeparateURI(HTTP_URI_CODING_ALL, device_uri, scheme, sizeof(scheme), userpass, sizeof(userpass), serviceName, sizeof(serviceName), &port, resource, sizeof(resource)) >= HTTP_URI_STATUS_OK)
+ {
+ if ((regtype = strstr(serviceName, "._ipp")) != NULL)
+ {
+ *regtype++ = '\0';
+
+ if ((replyDomain = strstr(regtype, "._tcp.")) != NULL)
+ {
+ replyDomain[5] = '\0';
+ replyDomain += 6;
+
+ if ((device = cups_dnssd_get_device(&data, serviceName, regtype, replyDomain)) != NULL)
+ device->state = _CUPS_DNSSD_ACTIVE;
+ }
+ }
+ }
+ }
+#endif /* HAVE_DNSSD || HAVE_AVAHI */
+ }
+
+ cupsFreeDests(num_dests, dests);
+
+ if (i > 0 || msec == 0)
+ goto enum_finished;
+ }
+
+ /*
+ * Return early if the caller doesn't want to do discovery...
+ */
+
+ if ((mask & CUPS_PRINTER_DISCOVERED) && !(type & CUPS_PRINTER_DISCOVERED))
+ goto enum_finished;
+
+#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
+ /*
+ * Get Bonjour-shared printers...
+ */
+
+ gettimeofday(&curtime, NULL);
+
+# ifdef HAVE_DNSSD
+ if (DNSServiceCreateConnection(&data.main_ref) != kDNSServiceErr_NoError)
+ {
+ DEBUG_puts("1cups_enum_dests: Unable to create service browser, returning 0.");
+ return (0);
+ }
+
+ main_fd = DNSServiceRefSockFD(data.main_ref);
+
+ ipp_ref = data.main_ref;
+ if (DNSServiceBrowse(&ipp_ref, kDNSServiceFlagsShareConnection, 0, "_ipp._tcp", NULL, (DNSServiceBrowseReply)cups_dnssd_browse_cb, &data) != kDNSServiceErr_NoError)
+ {
+ DEBUG_puts("1cups_enum_dests: Unable to create IPP browser, returning 0.");
+ DNSServiceRefDeallocate(data.main_ref);
+ return (0);
+ }
+
+ local_ipp_ref = data.main_ref;
+ if (DNSServiceBrowse(&local_ipp_ref, kDNSServiceFlagsShareConnection, kDNSServiceInterfaceIndexLocalOnly, "_ipp._tcp", NULL, (DNSServiceBrowseReply)cups_dnssd_local_cb, &data) != kDNSServiceErr_NoError)
+ {
+ DEBUG_puts("1cups_enum_dests: Unable to create local IPP browser, returning 0.");
+ DNSServiceRefDeallocate(data.main_ref);
+ return (0);
+ }
+
+# ifdef HAVE_SSL
+ ipps_ref = data.main_ref;
+ if (DNSServiceBrowse(&ipps_ref, kDNSServiceFlagsShareConnection, 0, "_ipps._tcp", NULL, (DNSServiceBrowseReply)cups_dnssd_browse_cb, &data) != kDNSServiceErr_NoError)
+ {
+ DEBUG_puts("1cups_enum_dests: Unable to create IPPS browser, returning 0.");
+ DNSServiceRefDeallocate(data.main_ref);
+ return (0);
+ }
+
+ local_ipps_ref = data.main_ref;
+ if (DNSServiceBrowse(&local_ipps_ref, kDNSServiceFlagsShareConnection, kDNSServiceInterfaceIndexLocalOnly, "_ipps._tcp", NULL, (DNSServiceBrowseReply)cups_dnssd_local_cb, &data) != kDNSServiceErr_NoError)
+ {
+ DEBUG_puts("1cups_enum_dests: Unable to create local IPPS browser, returning 0.");
+ DNSServiceRefDeallocate(data.main_ref);
+ return (0);
+ }
+# endif /* HAVE_SSL */
+
+# else /* HAVE_AVAHI */
+ if ((data.simple_poll = avahi_simple_poll_new()) == NULL)
+ {
+ DEBUG_puts("1cups_enum_dests: Unable to create Avahi poll, returning 0.");
+ return (0);
+ }
+
+ avahi_simple_poll_set_func(data.simple_poll, cups_dnssd_poll_cb, &data);
+
+ data.client = avahi_client_new(avahi_simple_poll_get(data.simple_poll),
+ 0, cups_dnssd_client_cb, &data,
+ &error);
+ if (!data.client)
+ {
+ DEBUG_puts("1cups_enum_dests: Unable to create Avahi client, returning 0.");
+ avahi_simple_poll_free(data.simple_poll);
+ return (0);
+ }
+
+ data.browsers = 1;
+ if ((ipp_ref = avahi_service_browser_new(data.client, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, "_ipp._tcp", NULL, 0, cups_dnssd_browse_cb, &data)) == NULL)
+ {
+ DEBUG_puts("1cups_enum_dests: Unable to create Avahi IPP browser, returning 0.");
+
+ avahi_client_free(data.client);
+ avahi_simple_poll_free(data.simple_poll);
+ return (0);
+ }
+
+# ifdef HAVE_SSL
+ data.browsers ++;
+ if ((ipps_ref = avahi_service_browser_new(data.client, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, "_ipps._tcp", NULL, 0, cups_dnssd_browse_cb, &data)) == NULL)
+ {
+ DEBUG_puts("1cups_enum_dests: Unable to create Avahi IPPS browser, returning 0.");
+
+ avahi_service_browser_free(ipp_ref);
+ avahi_client_free(data.client);
+ avahi_simple_poll_free(data.simple_poll);
+ return (0);
+ }
+# endif /* HAVE_SSL */
+# endif /* HAVE_DNSSD */
+
+ if (msec < 0)
+ remaining = INT_MAX;
+ else
+ remaining = msec;
+
+ while (remaining > 0 && (!cancel || !*cancel))
+ {
+ /*
+ * Check for input...
+ */
+
+ DEBUG_printf(("1cups_enum_dests: remaining=%d", remaining));
+
+ cups_elapsed(&curtime);
+
+# ifdef HAVE_DNSSD
+# ifdef HAVE_POLL
+ pfd.fd = main_fd;
+ pfd.events = POLLIN;
+
+ nfds = poll(&pfd, 1, remaining > _CUPS_DNSSD_MAXTIME ? _CUPS_DNSSD_MAXTIME : remaining);
+
+# else
+ FD_ZERO(&input);
+ FD_SET(main_fd, &input);
+
+ timeout.tv_sec = 0;
+ timeout.tv_usec = 1000 * (remaining > _CUPS_DNSSD_MAXTIME ? _CUPS_DNSSD_MAXTIME : remaining);
+
+ nfds = select(main_fd + 1, &input, NULL, NULL, &timeout);
+# endif /* HAVE_POLL */
+
+ if (nfds > 0)
+ DNSServiceProcessResult(data.main_ref);
+ else if (nfds < 0 && errno != EINTR && errno != EAGAIN)
+ break;
+
+# else /* HAVE_AVAHI */
+ data.got_data = 0;
+
+ if ((error = avahi_simple_poll_iterate(data.simple_poll, _CUPS_DNSSD_MAXTIME)) > 0)
+ {
+ /*
+ * We've been told to exit the loop. Perhaps the connection to
+ * Avahi failed.
+ */
+
+ break;
+ }
+
+ DEBUG_printf(("1cups_enum_dests: got_data=%d", data.got_data));
+# endif /* HAVE_DNSSD */
+
+ remaining -= cups_elapsed(&curtime);
+
+ for (device = (_cups_dnssd_device_t *)cupsArrayFirst(data.devices),
+ count = 0, completed = 0;
+ device;
+ device = (_cups_dnssd_device_t *)cupsArrayNext(data.devices))
+ {
+ if (device->ref)
+ count ++;
+
+ if (device->state == _CUPS_DNSSD_ACTIVE)
+ completed ++;
+
+ if (!device->ref && device->state == _CUPS_DNSSD_NEW)
+ {
+ DEBUG_printf(("1cups_enum_dests: Querying '%s'.", device->fullName));
+
+# ifdef HAVE_DNSSD
+ device->ref = data.main_ref;
+
+ if (DNSServiceQueryRecord(&(device->ref), kDNSServiceFlagsShareConnection, 0, device->fullName, kDNSServiceType_TXT, kDNSServiceClass_IN, (DNSServiceQueryRecordReply)cups_dnssd_query_cb, &data) == kDNSServiceErr_NoError)
+ {
+ count ++;
+ }
+ else
+ {
+ device->ref = 0;
+ device->state = _CUPS_DNSSD_ERROR;
+
+ DEBUG_puts("1cups_enum_dests: Query failed.");
+ }
+
+# else /* HAVE_AVAHI */
+ if ((device->ref = avahi_record_browser_new(data.client, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, device->fullName, AVAHI_DNS_CLASS_IN, AVAHI_DNS_TYPE_TXT, 0, cups_dnssd_query_cb, &data)) != NULL)
+ {
+ DEBUG_printf(("1cups_enum_dests: Query ref=%p", device->ref));
+ count ++;
+ }
+ else
+ {
+ device->state = _CUPS_DNSSD_ERROR;
+
+ DEBUG_printf(("1cups_enum_dests: Query failed: %s", avahi_strerror(avahi_client_errno(data.client))));
+ }
+# endif /* HAVE_DNSSD */
+ }
+ else if (device->ref && device->state == _CUPS_DNSSD_PENDING)
+ {
+ completed ++;
+
+ DEBUG_printf(("1cups_enum_dests: Query for \"%s\" is complete.", device->fullName));
+
+ if ((device->type & mask) == type)
+ {
+ DEBUG_printf(("1cups_enum_dests: Add callback for \"%s\".", device->dest.name));
+ if (!(*cb)(user_data, CUPS_DEST_FLAGS_NONE, &device->dest))
+ {
+ remaining = -1;
+ break;
+ }
+ }
+
+ device->state = _CUPS_DNSSD_ACTIVE;
+ }
+ }
+
+# ifdef HAVE_AVAHI
+ DEBUG_printf(("1cups_enum_dests: remaining=%d, browsers=%d, completed=%d, count=%d, devices count=%d", remaining, data.browsers, completed, count, cupsArrayCount(data.devices)));
+
+ if (data.browsers == 0 && completed == cupsArrayCount(data.devices))
+ break;
+# else
+ DEBUG_printf(("1cups_enum_dests: remaining=%d, completed=%d, count=%d, devices count=%d", remaining, completed, count, cupsArrayCount(data.devices)));
+
+ if (completed == cupsArrayCount(data.devices))
+ break;
+# endif /* HAVE_AVAHI */
+ }
+#endif /* HAVE_DNSSD || HAVE_AVAHI */
+
+ /*
+ * Return...
+ */
+
+ enum_finished:
+
+#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
+ cupsArrayDelete(data.devices);
+
+# ifdef HAVE_DNSSD
+ if (ipp_ref)
+ DNSServiceRefDeallocate(ipp_ref);
+ if (local_ipp_ref)
+ DNSServiceRefDeallocate(local_ipp_ref);
+
+# ifdef HAVE_SSL
+ if (ipps_ref)
+ DNSServiceRefDeallocate(ipps_ref);
+ if (local_ipps_ref)
+ DNSServiceRefDeallocate(local_ipps_ref);
+# endif /* HAVE_SSL */
+
+ if (data.main_ref)
+ DNSServiceRefDeallocate(data.main_ref);
+
+# else /* HAVE_AVAHI */
+ if (ipp_ref)
+ avahi_service_browser_free(ipp_ref);
+# ifdef HAVE_SSL
+ if (ipps_ref)
+ avahi_service_browser_free(ipps_ref);
+# endif /* HAVE_SSL */
+
+ if (data.client)
+ avahi_client_free(data.client);
+ if (data.simple_poll)
+ avahi_simple_poll_free(data.simple_poll);
+# endif /* HAVE_DNSSD */
+#endif /* HAVE_DNSSD || HAVE_AVAHI */
+
+ DEBUG_puts("1cups_enum_dests: Returning 1.");
+
+ return (1);
+}
+
+
/*
* 'cups_find_dest()' - Find a destination using a binary search.
*/
@@ -3724,6 +4079,36 @@ cups_find_dest(const char *name, /* I - Destination name */
/*
+ * 'cups_get_cb()' - Collect enumerated destinations.
+ */
+
+static int /* O - 1 to continue, 0 to stop */
+cups_get_cb(_cups_getdata_t *data, /* I - Data from cupsGetDests */
+ unsigned flags, /* I - Enumeration flags */
+ cups_dest_t *dest) /* I - Destination */
+{
+ if (flags & CUPS_DEST_FLAGS_REMOVED)
+ {
+ /*
+ * Remove destination from array...
+ */
+
+ data->num_dests = cupsRemoveDest(dest->name, dest->instance, data->num_dests, &data->dests);
+ }
+ else
+ {
+ /*
+ * Add destination to array...
+ */
+
+ data->num_dests = cupsCopyDest(dest, data->num_dests, &data->dests);
+ }
+
+ return (1);
+}
+
+
+/*
* 'cups_get_default()' - Get the default destination from an lpoptions file.
*/
@@ -4027,3 +4412,58 @@ cups_make_string(
return (buffer);
}
+
+
+/*
+ * 'cups_name_cb()' - Find an enumerated destination.
+ */
+
+static int /* O - 1 to continue, 0 to stop */
+cups_name_cb(_cups_namedata_t *data, /* I - Data from cupsGetNamedDest */
+ unsigned flags, /* I - Enumeration flags */
+ cups_dest_t *dest) /* I - Destination */
+{
+ DEBUG_printf(("2cups_name_cb(data=%p(%s), flags=%x, dest=%p(%s)", (void *)data, data->name, flags, (void *)dest, dest->name));
+
+ if (!(flags & CUPS_DEST_FLAGS_REMOVED) && !dest->instance && !strcasecmp(data->name, dest->name))
+ {
+ /*
+ * Copy destination and stop enumeration...
+ */
+
+ cupsCopyDest(dest, 0, &data->dest);
+ return (0);
+ }
+
+ return (1);
+}
+
+
+/*
+ * 'cups_queue_name()' - Create a local queue name based on the service name.
+ */
+
+static void
+cups_queue_name(
+ char *name, /* I - Name buffer */
+ const char *serviceName, /* I - Service name */
+ size_t namesize) /* I - Size of name buffer */
+{
+ const char *ptr; /* Pointer into serviceName */
+ char *nameptr; /* Pointer into name */
+
+
+ for (nameptr = name, ptr = serviceName; *ptr && nameptr < (name + namesize - 1); ptr ++)
+ {
+ /*
+ * Sanitize the printer name...
+ */
+
+ if (_cups_isalnum(*ptr))
+ *nameptr++ = *ptr;
+ else if (nameptr == name || nameptr[-1] != '_')
+ *nameptr++ = '_';
+ }
+
+ *nameptr = '\0';
+}
diff --git a/cups/dir.c b/cups/dir.c
index 65b8c4f9..b7cd400c 100644
--- a/cups/dir.c
+++ b/cups/dir.c
@@ -3,7 +3,7 @@
*
* This set of APIs abstracts enumeration of directory entries.
*
- * Copyright 2007-2012 by Apple Inc.
+ * Copyright 2007-2017 by Apple Inc.
* Copyright 1997-2005 by Easy Software Products, all rights reserved.
*
* These coded instructions, statements, and computer programs are the
@@ -338,10 +338,6 @@ cupsDirRead(cups_dir_t *dp) /* I - Directory pointer */
{
struct dirent *entry; /* Pointer to entry */
char filename[1024]; /* Full filename */
-# ifdef HAVE_PTHREAD_H
- char buffer[sizeof(struct dirent) + 1024];
- /* Directory entry buffer */
-# endif /* HAVE_PTHREAD_H */
DEBUG_printf(("2cupsDirRead(dp=%p)", (void *)dp));
@@ -359,29 +355,8 @@ cupsDirRead(cups_dir_t *dp) /* I - Directory pointer */
for (;;)
{
-# ifdef HAVE_PTHREAD_H
/*
- * Read the next entry using the reentrant version of readdir...
- */
-
- if (readdir_r(dp->dir, (struct dirent *)buffer, &entry))
- {
- DEBUG_printf(("3cupsDirRead: readdir_r() failed - %s\n", strerror(errno)));
- return (NULL);
- }
-
- if (!entry)
- {
- DEBUG_puts("3cupsDirRead: readdir_r() returned a NULL pointer!");
- return (NULL);
- }
-
- DEBUG_printf(("4cupsDirRead: readdir_r() returned \"%s\"...",
- entry->d_name));
-
-# else
- /*
- * Read the next entry using the original version of readdir...
+ * Read the next entry...
*/
if ((entry = readdir(dp->dir)) == NULL)
@@ -392,8 +367,6 @@ cupsDirRead(cups_dir_t *dp) /* I - Directory pointer */
DEBUG_printf(("4cupsDirRead: readdir() returned \"%s\"...", entry->d_name));
-# endif /* HAVE_PTHREAD_H */
-
/*
* Skip "." and ".."...
*/
diff --git a/cups/encode.c b/cups/encode.c
index e60aec0d..94695d08 100644
--- a/cups/encode.c
+++ b/cups/encode.c
@@ -1,7 +1,7 @@
/*
* Option encoding routines for CUPS.
*
- * Copyright 2007-2016 by Apple Inc.
+ * Copyright 2007-2017 by Apple Inc.
* Copyright 1997-2007 by Easy Software Products.
*
* These coded instructions, statements, and computer programs are the
@@ -329,7 +329,7 @@ static int compare_ipp_options(_ipp_option_t *a, _ipp_option_t *b);
* 'cupsEncodeOptions()' - Encode printer options into IPP attributes.
*
* This function adds operation, job, and then subscription attributes,
- * in that order. Use the cupsEncodeOptions2() function to add attributes
+ * in that order. Use the @link cupsEncodeOptions2@ function to add attributes
* for a single group.
*/
@@ -354,7 +354,7 @@ cupsEncodeOptions(ipp_t *ipp, /* I - Request to add to */
* 'cupsEncodeOptions2()' - Encode printer options into IPP attributes for a group.
*
* This function only adds attributes for a single group. Call this
- * function multiple times for each group, or use cupsEncodeOptions()
+ * function multiple times for each group, or use @link cupsEncodeOptions@
* to add the standard groups.
*
* @since CUPS 1.2/macOS 10.5@
diff --git a/cups/file-private.h b/cups/file-private.h
index b8ca431f..1f4db798 100644
--- a/cups/file-private.h
+++ b/cups/file-private.h
@@ -4,9 +4,9 @@
* Since stdio files max out at 256 files on many systems, we have to
* write similar functions without this limit. At the same time, using
* our own file functions allows us to provide transparent support of
- * gzip'd print files, PPD files, etc.
+ * different line endings, gzip'd print files, PPD files, etc.
*
- * Copyright 2007-2014 by Apple Inc.
+ * Copyright 2007-2017 by Apple Inc.
* Copyright 1997-2007 by Easy Software Products, all rights reserved.
*
* These coded instructions, statements, and computer programs are the
diff --git a/cups/file.c b/cups/file.c
index a027df40..5d150540 100644
--- a/cups/file.c
+++ b/cups/file.c
@@ -4,9 +4,9 @@
* Since stdio files max out at 256 files on many systems, we have to
* write similar functions without this limit. At the same time, using
* our own file functions allows us to provide transparent support of
- * gzip'd print files, PPD files, etc.
+ * different line endings, gzip'd print files, PPD files, etc.
*
- * Copyright 2007-2015 by Apple Inc.
+ * Copyright 2007-2017 by Apple Inc.
* Copyright 1997-2007 by Easy Software Products, all rights reserved.
*
* These coded instructions, statements, and computer programs are the
@@ -321,7 +321,6 @@ cupsFileClose(cups_file_t *fp) /* I - CUPS file */
int fd; /* File descriptor */
char mode; /* Open mode */
int status; /* Return status */
- int is_stdio; /* Is a stdio file? */
DEBUG_printf(("cupsFileClose(fp=%p)", (void *)fp));
@@ -410,12 +409,19 @@ cupsFileClose(cups_file_t *fp) /* I - CUPS file */
#endif /* HAVE_LIBZ */
/*
+ * If this is one of the cupsFileStdin/out/err files, return now and don't
+ * actually free memory or close (these last the life of the process...)
+ */
+
+ if (fp->is_stdio)
+ return (status);
+
+/*
* Save the file descriptor we used and free memory...
*/
- fd = fp->fd;
- mode = fp->mode;
- is_stdio = fp->is_stdio;
+ fd = fp->fd;
+ mode = fp->mode;
if (fp->printf_buffer)
free(fp->printf_buffer);
@@ -431,11 +437,8 @@ cupsFileClose(cups_file_t *fp) /* I - CUPS file */
if (httpAddrClose(NULL, fd) < 0)
status = -1;
}
- else if (!is_stdio)
- {
- if (close(fd) < 0)
- status = -1;
- }
+ else if (close(fd) < 0)
+ status = -1;
return (status);
}
@@ -1384,7 +1387,11 @@ cupsFilePrintf(cups_file_t *fp, /* I - CUPS file */
{
memcpy(fp->ptr, fp->printf_buffer, (size_t)bytes);
fp->ptr += bytes;
- return ((int)bytes);
+
+ if (fp->is_stdio && cupsFileFlush(fp))
+ return (-1);
+ else
+ return ((int)bytes);
}
}
@@ -1563,7 +1570,11 @@ cupsFilePuts(cups_file_t *fp, /* I - CUPS file */
{
memcpy(fp->ptr, s, (size_t)bytes);
fp->ptr += bytes;
- return ((int)bytes);
+
+ if (fp->is_stdio && cupsFileFlush(fp))
+ return (-1);
+ else
+ return ((int)bytes);
}
}
@@ -2466,6 +2477,8 @@ cups_fill(cups_file_t *fp) /* I - CUPS file */
* file header...
*/
+ inflateEnd(&fp->stream);
+
fp->compressed = 0;
}
else if (status < Z_OK)
diff --git a/cups/file.h b/cups/file.h
index 177c2e90..42abe208 100644
--- a/cups/file.h
+++ b/cups/file.h
@@ -4,9 +4,9 @@
* Since stdio files max out at 256 files on many systems, we have to
* write similar functions without this limit. At the same time, using
* our own file functions allows us to provide transparent support of
- * gzip'd print files, PPD files, etc.
+ * different line endings, gzip'd print files, PPD files, etc.
*
- * Copyright 2007-2014 by Apple Inc.
+ * Copyright 2007-2017 by Apple Inc.
* Copyright 1997-2007 by Easy Software Products, all rights reserved.
*
* These coded instructions, statements, and computer programs are the
diff --git a/cups/http-addr.c b/cups/http-addr.c
index 12d13a69..61c86384 100644
--- a/cups/http-addr.c
+++ b/cups/http-addr.c
@@ -58,9 +58,9 @@ httpAddrAny(const http_addr_t *addr) /* I - Address to check */
* 'httpAddrClose()' - Close a socket created by @link httpAddrConnect@ or
* @link httpAddrListen@.
*
- * Pass @code NULL@ for sockets created with @link httpAddrConnect@ and the
- * listen address for sockets created with @link httpAddrListen@. This will
- * ensure that domain sockets are removed when closed.
+ * Pass @code NULL@ for sockets created with @link httpAddrConnect2@ and the
+ * listen address for sockets created with @link httpAddrListen@. This function
+ * ensures that domain sockets are removed when closed.
*
* @since CUPS 2.0/OS 10.10@
*/
@@ -648,6 +648,10 @@ httpAddrString(const http_addr_t *addr, /* I - Address to convert */
/*
* 'httpGetAddress()' - Get the address of the connected peer of a connection.
*
+ * For connections created with @link httpConnect2@, the address is for the
+ * server. For connections created with @link httpAccept@, the address is for
+ * the client.
+ *
* Returns @code NULL@ if the socket is currently unconnected.
*
* @since CUPS 2.0/OS 10.10@
@@ -667,7 +671,7 @@ httpGetAddress(http_t *http) /* I - HTTP connection */
* 'httpGetHostByName()' - Lookup a hostname or IPv4 address, and return
* address records for the specified name.
*
- * @deprecated@
+ * @deprecated@ @exclude all@
*/
struct hostent * /* O - Host entry */
diff --git a/cups/http-addrlist.c b/cups/http-addrlist.c
index 723bf029..e5fc940e 100644
--- a/cups/http-addrlist.c
+++ b/cups/http-addrlist.c
@@ -1,7 +1,7 @@
/*
* HTTP address list routines for CUPS.
*
- * Copyright 2007-2016 by Apple Inc.
+ * Copyright 2007-2017 by Apple Inc.
* Copyright 1997-2007 by Easy Software Products, all rights reserved.
*
* These coded instructions, statements, and computer programs are the
@@ -32,7 +32,7 @@
/*
* 'httpAddrConnect()' - Connect to any of the addresses in the list.
*
- * @since CUPS 1.2/macOS 10.5@
+ * @since CUPS 1.2/macOS 10.5@ @exclude all@
*/
http_addrlist_t * /* O - Connected address or NULL on failure */
@@ -65,7 +65,7 @@ httpAddrConnect2(
int flags; /* Socket flags */
#endif /* !WIN32 */
int remaining; /* Remaining timeout */
- int i, /* Looping var */
+ int i, j, /* Looping vars */
nfds, /* Number of file descriptors */
fds[100], /* Socket file descriptors */
result; /* Result from select() or poll() */
@@ -323,6 +323,8 @@ httpAddrConnect2(
if (!getpeername(fds[i], (struct sockaddr *)&peer, &len))
DEBUG_printf(("1httpAddrConnect2: Connected to %s:%d...", httpAddrString(&peer, temp, sizeof(temp)), httpAddrPort(&peer)));
# endif /* DEBUG */
+
+ break;
}
# ifdef HAVE_POLL
else if (pfds[i].revents & (POLLERR | POLLHUP))
@@ -346,7 +348,20 @@ httpAddrConnect2(
}
if (connaddr)
+ {
+ /*
+ * Connected on one address, close all of the other sockets we have so
+ * far and return...
+ */
+
+ for (j = 0; j < i; j ++)
+ httpAddrClose(NULL, fds[j]);
+
+ for (j ++; j < nfds; j ++)
+ httpAddrClose(NULL, fds[j]);
+
return (connaddr);
+ }
}
#endif /* O_NONBLOCK */
diff --git a/cups/http-private.h b/cups/http-private.h
index ec908a66..f71e564b 100644
--- a/cups/http-private.h
+++ b/cups/http-private.h
@@ -1,7 +1,7 @@
/*
* Private HTTP definitions for CUPS.
*
- * Copyright 2007-2016 by Apple Inc.
+ * Copyright 2007-2017 by Apple Inc.
* Copyright 1997-2007 by Easy Software Products, all rights reserved.
*
* These coded instructions, statements, and computer programs are the
@@ -172,18 +172,20 @@ extern "C" {
* Constants...
*/
-
-#define _HTTP_MAX_SBUFFER 65536 /* Size of (de)compression buffer */
-#define _HTTP_RESOLVE_DEFAULT 0 /* Just resolve with default options */
-#define _HTTP_RESOLVE_STDERR 1 /* Log resolve progress to stderr */
-#define _HTTP_RESOLVE_FQDN 2 /* Resolve to a FQDN */
-#define _HTTP_RESOLVE_FAXOUT 4 /* Resolve FaxOut service? */
-
-#define _HTTP_TLS_NONE 0 /* No TLS options */
-#define _HTTP_TLS_ALLOW_RC4 1 /* Allow RC4 cipher suites */
-#define _HTTP_TLS_ALLOW_SSL3 2 /* Allow SSL 3.0 */
-#define _HTTP_TLS_ALLOW_DH 4 /* Allow DH/DHE key negotiation */
-#define _HTTP_TLS_DENY_TLS10 16 /* Deny TLS 1.0 */
+# define _HTTP_MAX_SBUFFER 65536 /* Size of (de)compression buffer */
+# define _HTTP_RESOLVE_DEFAULT 0 /* Just resolve with default options */
+# define _HTTP_RESOLVE_STDERR 1 /* Log resolve progress to stderr */
+# define _HTTP_RESOLVE_FQDN 2 /* Resolve to a FQDN */
+# define _HTTP_RESOLVE_FAXOUT 4 /* Resolve FaxOut service? */
+
+# define _HTTP_TLS_NONE 0 /* No TLS options */
+# define _HTTP_TLS_ALLOW_RC4 1 /* Allow RC4 cipher suites */
+# define _HTTP_TLS_ALLOW_SSL3 2 /* Allow SSL 3.0 */
+# define _HTTP_TLS_ALLOW_DH 4 /* Allow DH/DHE key negotiation */
+# define _HTTP_TLS_DENY_TLS10 16 /* Deny TLS 1.0 */
+# define _HTTP_TLS_DENY_CBC 32 /* Deny CBC cipher suites */
+# define _HTTP_TLS_ONLY_TLS10 64 /* Only use TLS 1.0 */
+# define _HTTP_TLS_SET_DEFAULT 128 /* Setting the default TLS options */
/*
diff --git a/cups/http-support.c b/cups/http-support.c
index 1ca01b27..76dbb7db 100644
--- a/cups/http-support.c
+++ b/cups/http-support.c
@@ -1,7 +1,7 @@
/*
* HTTP support routines for CUPS.
*
- * Copyright 2007-2016 by Apple Inc.
+ * Copyright 2007-2017 by Apple Inc.
* Copyright 1997-2007 by Easy Software Products, all rights reserved.
*
* These coded instructions, statements, and computer programs are the
@@ -543,7 +543,7 @@ httpAssembleUUID(const char *server, /* I - Server name */
* This function is deprecated. Use the httpDecode64_2() function instead
* which provides buffer length arguments.
*
- * @deprecated@
+ * @deprecated@ @exclude all@
*/
char * /* O - Decoded string */
@@ -566,6 +566,10 @@ httpDecode64(char *out, /* I - String to write to */
/*
* 'httpDecode64_2()' - Base64-decode a string.
*
+ * The caller must initialize "outlen" to the maximum size of the decoded
+ * string before calling @code httpDecode64_2@. On return "outlen" contains the
+ * decoded length of the string.
+ *
* @since CUPS 1.1.21/macOS 10.4@
*/
@@ -671,7 +675,7 @@ httpDecode64_2(char *out, /* I - String to write to */
* This function is deprecated. Use the httpEncode64_2() function instead
* which provides buffer length arguments.
*
- * @deprecated@
+ * @deprecated@ @exclude all@
*/
char * /* O - Encoded string */
@@ -690,7 +694,7 @@ httpEncode64(char *out, /* I - String to write to */
char * /* O - Encoded string */
httpEncode64_2(char *out, /* I - String to write to */
- int outlen, /* I - Size of output string */
+ int outlen, /* I - Maximum size of output string */
const char *in, /* I - String to read from */
int inlen) /* I - Size of input string */
{
@@ -778,11 +782,11 @@ httpEncode64_2(char *out, /* I - String to write to */
/*
* 'httpGetDateString()' - Get a formatted date/time string from a time value.
*
- * @deprecated@
+ * @deprecated@ @exclude all@
*/
const char * /* O - Date/time string */
-httpGetDateString(time_t t) /* I - UNIX time */
+httpGetDateString(time_t t) /* I - Time in seconds */
{
_cups_globals_t *cg = _cupsGlobals(); /* Pointer to library globals */
@@ -798,7 +802,7 @@ httpGetDateString(time_t t) /* I - UNIX time */
*/
const char * /* O - Date/time string */
-httpGetDateString2(time_t t, /* I - UNIX time */
+httpGetDateString2(time_t t, /* I - Time in seconds */
char *s, /* I - String buffer */
int slen) /* I - Size of string buffer */
{
@@ -819,7 +823,7 @@ httpGetDateString2(time_t t, /* I - UNIX time */
* 'httpGetDateTime()' - Get a time value from a formatted date/time string.
*/
-time_t /* O - UNIX time */
+time_t /* O - Time in seconds */
httpGetDateTime(const char *s) /* I - Date/time string */
{
int i; /* Looping var */
@@ -888,7 +892,7 @@ httpGetDateTime(const char *s) /* I - Date/time string */
*
* This function is deprecated; use the httpSeparateURI() function instead.
*
- * @deprecated@
+ * @deprecated@ @exclude all@
*/
void
@@ -912,7 +916,7 @@ httpSeparate(const char *uri, /* I - Universal Resource Identifier */
* This function is deprecated; use the httpSeparateURI() function instead.
*
* @since CUPS 1.1.21/macOS 10.4@
- * @deprecated@
+ * @deprecated@ @exclude all@
*/
void
@@ -1419,7 +1423,7 @@ _httpStatus(cups_lang_t *lang, /* I - Language */
* 'httpStatus()' - Return a short string describing a HTTP status code.
*
* The returned string is localized to the current POSIX locale and is based
- * on the status strings defined in RFC 2616.
+ * on the status strings defined in RFC 7231.
*/
const char * /* O - Localized status string */
@@ -2310,6 +2314,8 @@ http_resolve_cb(
* Note: This function is needed because avahi_simple_poll_iterate is broken
* and always uses a timeout of 0 (!) milliseconds.
* (Avahi Ticket #364)
+ *
+ * @private@
*/
static int /* O - Number of file descriptors matching */
diff --git a/cups/http.c b/cups/http.c
index 7925513a..61b88c9d 100644
--- a/cups/http.c
+++ b/cups/http.c
@@ -1,7 +1,7 @@
/*
* HTTP routines for CUPS.
*
- * Copyright 2007-2015 by Apple Inc.
+ * Copyright 2007-2017 by Apple Inc.
* Copyright 1997-2007 by Easy Software Products, all rights reserved.
*
* This file contains Kerberos support code, copyright 2006 by
@@ -417,7 +417,7 @@ httpCompareCredentials(
*
* This function is deprecated - use @link httpConnect2@ instead.
*
- * @deprecated@
+ * @deprecated@ @exclude all@
*/
http_t * /* O - New HTTP connection */
@@ -439,7 +439,7 @@ http_t * /* O - New HTTP connection */
httpConnect2(
const char *host, /* I - Host to connect to */
int port, /* I - Port number */
- http_addrlist_t *addrlist, /* I - List of addresses or NULL to lookup */
+ http_addrlist_t *addrlist, /* I - List of addresses or @code NULL@ to lookup */
int family, /* I - Address family to use or @code AF_UNSPEC@ for any */
http_encryption_t encryption, /* I - Type of encryption to use */
int blocking, /* I - 1 for blocking connection, 0 for non-blocking */
@@ -482,7 +482,7 @@ httpConnect2(
* This function is now deprecated. Please use the @link httpConnect2@ function
* instead.
*
- * @deprecated@
+ * @deprecated@ @exclude all@
*/
http_t * /* O - New HTTP connection */
@@ -609,7 +609,7 @@ httpFieldValue(const char *name) /* I - String name */
/*
- * 'httpFlush()' - Flush data from a HTTP connection.
+ * 'httpFlush()' - Flush data read from a HTTP connection.
*/
void
@@ -679,7 +679,7 @@ httpFlush(http_t *http) /* I - HTTP connection */
/*
- * 'httpFlushWrite()' - Flush data in write buffer.
+ * 'httpFlushWrite()' - Flush data written to a HTTP connection.
*
* @since CUPS 1.2/macOS 10.5@
*/
@@ -751,7 +751,7 @@ httpGet(http_t *http, /* I - HTTP connection */
/*
* 'httpGetActivity()' - Get the most recent activity for a connection.
*
- * The return value is the UNIX time of the last read or write.
+ * The return value is the time in seconds of the last read or write.
*
* @since CUPS 2.0/OS 10.10@
*/
@@ -766,10 +766,10 @@ httpGetActivity(http_t *http) /* I - HTTP connection */
/*
* 'httpGetAuthString()' - Get the current authorization string.
*
- * The authorization string is set by cupsDoAuthentication() and
- * httpSetAuthString(). Use httpGetAuthString() to retrieve the
- * string to use with httpSetField() for the HTTP_FIELD_AUTHORIZATION
- * value.
+ * The authorization string is set by @link cupsDoAuthentication@ and
+ * @link httpSetAuthString@. Use @link httpGetAuthString@ to retrieve the
+ * string to use with @link httpSetField@ for the
+ * @code HTTP_FIELD_AUTHORIZATION@ value.
*
* @since CUPS 1.3/macOS 10.5@
*/
@@ -891,7 +891,7 @@ httpGetContentEncoding(http_t *http) /* I - HTTP connection */
* @since CUPS 1.1.19/macOS 10.3@
*/
-const char * /* O - Cookie data or NULL */
+const char * /* O - Cookie data or @code NULL@ */
httpGetCookie(http_t *http) /* I - HTTP connection */
{
return (http ? http->cookie : NULL);
@@ -1006,7 +1006,7 @@ httpGetKeepAlive(http_t *http) /* I - HTTP connection */
* This function is deprecated and will not return lengths larger than
* 2^31 - 1; use httpGetLength2() instead.
*
- * @deprecated@
+ * @deprecated@ @exclude all@
*/
int /* O - Content length */
@@ -1150,7 +1150,7 @@ httpGetRemaining(http_t *http) /* I - HTTP connection */
* 'httpGets()' - Get a line of text from a HTTP connection.
*/
-char * /* O - Line or NULL */
+char * /* O - Line or @code NULL@ */
httpGets(char *line, /* I - Line to read into */
int length, /* I - Max length of buffer */
http_t *http) /* I - HTTP connection */
@@ -1346,10 +1346,10 @@ httpGetStatus(http_t *http) /* I - HTTP connection */
/*
* 'httpGetSubField()' - Get a sub-field value.
*
- * @deprecated@
+ * @deprecated@ @exclude all@
*/
-char * /* O - Value or NULL */
+char * /* O - Value or @code NULL@ */
httpGetSubField(http_t *http, /* I - HTTP connection */
http_field_t field, /* I - Field index */
const char *name, /* I - Name of sub-field */
@@ -1365,7 +1365,7 @@ httpGetSubField(http_t *http, /* I - HTTP connection */
* @since CUPS 1.2/macOS 10.5@
*/
-char * /* O - Value or NULL */
+char * /* O - Value or @code NULL@ */
httpGetSubField2(http_t *http, /* I - HTTP connection */
http_field_t field, /* I - Field index */
const char *name, /* I - Name of sub-field */
@@ -1616,7 +1616,7 @@ httpOptions(http_t *http, /* I - HTTP connection */
*
* This function copies available data from the given HTTP connection, reading
* a buffer as needed. The data is still available for reading using
- * @link httpRead@ or @link httpRead2@.
+ * @link httpRead2@.
*
* For non-blocking connections the usual timeouts apply.
*
@@ -1939,7 +1939,7 @@ httpPut(http_t *http, /* I - HTTP connection */
* This function is deprecated. Use the httpRead2() function which can
* read more than 2GB of data.
*
- * @deprecated@
+ * @deprecated@ @exclude all@
*/
int /* O - Number of bytes read */
@@ -2326,7 +2326,7 @@ httpReadRequest(http_t *http, /* I - HTTP connection */
* This function is deprecated. Please use the @link httpReconnect2@ function
* instead.
*
- * @deprecated@
+ * @deprecated@ @exclude all@
*/
int /* O - 0 on success, non-zero on failure */
@@ -2467,9 +2467,10 @@ httpReconnect2(http_t *http, /* I - HTTP connection */
* 'httpSetAuthString()' - Set the current authorization string.
*
* This function just stores a copy of the current authorization string in
- * the HTTP connection object. You must still call httpSetField() to set
- * HTTP_FIELD_AUTHORIZATION prior to issuing a HTTP request using httpGet(),
- * httpHead(), httpOptions(), httpPost, or httpPut().
+ * the HTTP connection object. You must still call @link httpSetField@ to set
+ * @code HTTP_FIELD_AUTHORIZATION@ prior to issuing a HTTP request using
+ * @link httpGet@, @link httpHead@, @link httpOptions@, @link httpPost@, or
+ * @link httpPut@.
*
* @since CUPS 1.3/macOS 10.5@
*/
@@ -2820,7 +2821,7 @@ httpSetTimeout(
http_t *http, /* I - HTTP connection */
double timeout, /* I - Number of seconds for timeout,
must be greater than 0 */
- http_timeout_cb_t cb, /* I - Callback function or NULL */
+ http_timeout_cb_t cb, /* I - Callback function or @code NULL@ */
void *user_data) /* I - User data pointer */
{
if (!http || timeout <= 0.0)
@@ -2864,6 +2865,8 @@ httpShutdown(http_t *http) /* I - HTTP connection */
/*
* 'httpTrace()' - Send an TRACE request to the server.
+ *
+ * @exclude all@
*/
int /* O - Status of call (0 = success) */
@@ -3259,7 +3262,7 @@ httpWait(http_t *http, /* I - HTTP connection */
* This function is deprecated. Use the httpWrite2() function which can
* write more than 2GB of data.
*
- * @deprecated@
+ * @deprecated@ @exclude all@
*/
int /* O - Number of bytes written */
@@ -3898,7 +3901,7 @@ static http_t * /* O - HTTP connection */
http_create(
const char *host, /* I - Hostname */
int port, /* I - Port number */
- http_addrlist_t *addrlist, /* I - Address list or NULL */
+ http_addrlist_t *addrlist, /* I - Address list or @code NULL@ */
int family, /* I - Address family or AF_UNSPEC */
http_encryption_t encryption, /* I - Encryption to use */
int blocking, /* I - 1 for blocking mode */
diff --git a/cups/http.h b/cups/http.h
index ccbf77ee..c61a79ee 100644
--- a/cups/http.h
+++ b/cups/http.h
@@ -1,7 +1,7 @@
/*
* Hyper-Text Transport Protocol definitions for CUPS.
*
- * Copyright 2007-2014 by Apple Inc.
+ * Copyright 2007-2017 by Apple Inc.
* Copyright 1997-2007 by Easy Software Products, all rights reserved.
*
* These coded instructions, statements, and computer programs are the
@@ -109,7 +109,7 @@ extern "C" {
* Types and structures...
*/
-typedef enum http_auth_e /**** HTTP authentication types ****/
+typedef enum http_auth_e /**** HTTP authentication types @exclude all@ ****/
{
HTTP_AUTH_NONE, /* No authentication in use */
HTTP_AUTH_BASIC, /* Basic authentication in use */
@@ -393,7 +393,7 @@ typedef enum http_uri_coding_e /**** URI en/decode flags ****/
HTTP_URI_CODING_RFC6874 = 16 /* Use RFC 6874 address format */
} http_uri_coding_t;
-typedef enum http_version_e /**** HTTP version numbers ****/
+typedef enum http_version_e /**** HTTP version numbers @exclude all@ ****/
{
HTTP_VERSION_0_9 = 9, /* HTTP/0.9 */
HTTP_VERSION_1_0 = 100, /* HTTP/1.0 */
@@ -427,6 +427,7 @@ typedef struct http_addrlist_s /**** Socket address list, which is
**** used to enumerate all of the
**** addresses that are associated
**** with a hostname. @since CUPS 1.2/macOS 10.5@
+ **** @exclude all@
****/
{
struct http_addrlist_s *next; /* Pointer to next address in list */
@@ -435,7 +436,7 @@ typedef struct http_addrlist_s /**** Socket address list, which is
typedef struct _http_s http_t; /**** HTTP connection type ****/
-typedef struct http_credential_s /**** HTTP credential data @since CUPS 1.5/macOS 10.7@ ****/
+typedef struct http_credential_s /**** HTTP credential data @since CUPS 1.5/macOS 10.7@ @exclude all@ ****/
{
void *data; /* Pointer to credential data */
size_t datalen; /* Credential length */
diff --git a/cups/ipp-support.c b/cups/ipp-support.c
index b49ac0d2..675e5f38 100644
--- a/cups/ipp-support.c
+++ b/cups/ipp-support.c
@@ -1,7 +1,7 @@
/*
* Internet Printing Protocol support functions for CUPS.
*
- * Copyright 2007-2014 by Apple Inc.
+ * Copyright 2007-2017 by Apple Inc.
* Copyright 1997-2007 by Easy Software Products, all rights reserved.
*
* These coded instructions, statements, and computer programs are the
@@ -2243,7 +2243,7 @@ ippStateString(ipp_state_t state) /* I - State value */
/*
* 'ippTagString()' - Return the tag name corresponding to a tag value.
*
- * The returned names are defined in RFC 2911 and 3382.
+ * The returned names are defined in RFC 8011 and the IANA IPP Registry.
*
* @since CUPS 1.4/macOS 10.6@
*/
@@ -2263,7 +2263,7 @@ ippTagString(ipp_tag_t tag) /* I - Tag value */
/*
* 'ippTagValue()' - Return the tag value corresponding to a tag name.
*
- * The tag names are defined in RFC 2911 and 3382.
+ * The tag names are defined in RFC 8011 and the IANA IPP Registry.
*
* @since CUPS 1.4/macOS 10.6@
*/
diff --git a/cups/ipp.c b/cups/ipp.c
index 817c9d5f..772b2f0a 100644
--- a/cups/ipp.c
+++ b/cups/ipp.c
@@ -316,7 +316,7 @@ ippAddCollections(
/*
- * 'ippAddDate()' - Add a date attribute to an IPP message.
+ * 'ippAddDate()' - Add a dateTime attribute to an IPP message.
*
* The @code ipp@ parameter refers to an IPP message previously created using
* the @link ippNew@, @link ippNewRequest@, or @link ippNewResponse@ functions.
@@ -1380,7 +1380,7 @@ ippContainsInteger(
* specified string value.
*
* Returns non-zero when the attribute contains a matching charset, keyword,
- * language, mimeMediaType, name, text, URI, or URI scheme value.
+ * naturalLanguage, mimeMediaType, name, text, uri, or uriScheme value.
*
* @since CUPS 1.7/macOS 10.9@
*/
@@ -1509,6 +1509,16 @@ ippCopyAttribute(
dstattr = ippAddSeparator(dst);
break;
+ 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 :
+ dstattr = ippAddOutOfBand(dst, srcattr->group_tag, srcattr->value_tag & ~IPP_TAG_CUPS_CONST, srcattr->name);
+ break;
+
case IPP_TAG_INTEGER :
case IPP_TAG_ENUM :
dstattr = ippAddIntegers(dst, srcattr->group_tag, srcattr->value_tag,
@@ -1759,12 +1769,12 @@ ippCopyAttributes(
/*
- * 'ippDateToTime()' - Convert from RFC 1903 Date/Time format to UNIX time
- * in seconds.
+ * 'ippDateToTime()' - Convert from RFC 2579 Date/Time format to time in
+ * seconds.
*/
time_t /* O - UNIX time value */
-ippDateToTime(const ipp_uchar_t *date) /* I - RFC 1903 date info */
+ippDateToTime(const ipp_uchar_t *date) /* I - RFC 2579 date info */
{
struct tm unixdate; /* UNIX date/time info */
time_t t; /* Computed time */
@@ -1776,7 +1786,7 @@ ippDateToTime(const ipp_uchar_t *date) /* I - RFC 1903 date info */
memset(&unixdate, 0, sizeof(unixdate));
/*
- * RFC-1903 date/time format is:
+ * RFC-2579 date/time format is:
*
* Byte(s) Description
* ------- -----------
@@ -1828,12 +1838,19 @@ ippDelete(ipp_t *ipp) /* I - IPP message */
ipp->use --;
if (ipp->use > 0)
+ {
+ DEBUG_printf(("4debug_retain: %p IPP message (use=%d)", (void *)ipp, ipp->use));
return;
+ }
+
+ DEBUG_printf(("4debug_free: %p IPP message", (void *)ipp));
for (attr = ipp->attrs; attr != NULL; attr = next)
{
next = attr->next;
+ DEBUG_printf(("4debug_free: %p %s %s%s (%d values)", (void *)attr, attr->name, attr->num_values > 1 ? "1setOf " : "", ippTagString(attr->value_tag), attr->num_values));
+
ipp_free_values(attr, 0, attr->num_values);
if (attr->name)
@@ -1870,6 +1887,8 @@ ippDeleteAttribute(
if (!attr)
return;
+ DEBUG_printf(("4debug_free: %p %s %s%s (%d values)", (void *)attr, attr->name, attr->num_values > 1 ? "1setOf " : "", ippTagString(attr->value_tag), attr->num_values));
+
/*
* Find the attribute in the list...
*/
@@ -2152,7 +2171,7 @@ ippFirstAttribute(ipp_t *ipp) /* I - IPP message */
* 'ippGetBoolean()' - Get a boolean value for an attribute.
*
* The @code element@ parameter specifies which value to get from 0 to
- * @link ippGetCount(attr)@ - 1.
+ * @code ippGetCount(attr)@ - 1.
*
* @since CUPS 1.6/macOS 10.8@
*/
@@ -2181,7 +2200,7 @@ ippGetBoolean(ipp_attribute_t *attr, /* I - IPP attribute */
* 'ippGetCollection()' - Get a collection value for an attribute.
*
* The @code element@ parameter specifies which value to get from 0 to
- * @link ippGetCount(attr)@ - 1.
+ * @code ippGetCount(attr)@ - 1.
*
* @since CUPS 1.6/macOS 10.8@
*/
@@ -2232,15 +2251,15 @@ ippGetCount(ipp_attribute_t *attr) /* I - IPP attribute */
/*
- * 'ippGetDate()' - Get a date value for an attribute.
+ * 'ippGetDate()' - Get a dateTime value for an attribute.
*
* The @code element@ parameter specifies which value to get from 0 to
- * @link ippGetCount(attr)@ - 1.
+ * @code ippGetCount(attr)@ - 1.
*
* @since CUPS 1.6/macOS 10.8@
*/
-const ipp_uchar_t * /* O - Date value or @code NULL@ */
+const ipp_uchar_t * /* O - dateTime value or @code NULL@ */
ippGetDate(ipp_attribute_t *attr, /* I - IPP attribute */
int element) /* I - Value number (0-based) */
{
@@ -2288,7 +2307,7 @@ ippGetGroupTag(ipp_attribute_t *attr) /* I - IPP attribute */
* '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.
+ * @code ippGetCount(attr)@ - 1.
*
* @since CUPS 1.6/macOS 10.8@
*/
@@ -2341,7 +2360,7 @@ ippGetName(ipp_attribute_t *attr) /* I - IPP attribute */
* 'ippGetOctetString()' - Get an octetString value from an IPP attribute.
*
* The @code element@ parameter specifies which value to get from 0 to
- * @link ippGetCount(attr)@ - 1.
+ * @code ippGetCount(attr)@ - 1.
*
* @since CUPS 1.7/macOS 10.9@
*/
@@ -2404,7 +2423,7 @@ ippGetOperation(ipp_t *ipp) /* I - IPP request message */
* 'ippGetRange()' - Get a rangeOfInteger value from an attribute.
*
* The @code element@ parameter specifies which value to get from 0 to
- * @link ippGetCount(attr)@ - 1.
+ * @code ippGetCount(attr)@ - 1.
*
* @since CUPS 1.6/macOS 10.8@
*/
@@ -2466,7 +2485,7 @@ ippGetRequestId(ipp_t *ipp) /* I - IPP message */
* 'ippGetResolution()' - Get a resolution value for an attribute.
*
* The @code element@ parameter specifies which value to get from 0 to
- * @link ippGetCount(attr)@ - 1.
+ * @code ippGetCount(attr)@ - 1.
*
* @since CUPS 1.6/macOS 10.8@
*/
@@ -2560,7 +2579,7 @@ ippGetStatusCode(ipp_t *ipp) /* I - IPP response or event message */
* '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.
+ * @code ippGetCount(attr)@ - 1.
*
* @since CUPS 1.6/macOS 10.8@
*/
@@ -2625,7 +2644,7 @@ ippGetValueTag(ipp_attribute_t *attr) /* I - IPP attribute */
int /* O - Major version number or 0 on error */
ippGetVersion(ipp_t *ipp, /* I - IPP message */
- int *minor) /* O - Minor version number or @code NULL@ */
+ int *minor) /* O - Minor version number or @code NULL@ for don't care */
{
/*
* Range check input...
@@ -2705,6 +2724,8 @@ ippNew(void)
* Set default version - usually 2.0...
*/
+ DEBUG_printf(("4debug_alloc: %p IPP message", (void *)temp));
+
if (cg->server_version == 0)
_cupsSetDefaults();
@@ -2722,9 +2743,9 @@ ippNew(void)
/*
* '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.
+ * 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/macOS 10.5@
*/
@@ -2786,11 +2807,11 @@ ippNewRequest(ipp_op_t op) /* I - Operation code */
/*
* 'ippNewResponse()' - Allocate a new IPP response message.
*
- * The new response message is initialized with the same version-number,
- * request-id, attributes-charset, and attributes-natural-language as the
- * provided request message. If the attributes-charset or
- * attributes-natural-language attributes are missing from the request,
- * "utf-8" and a value derived from the current locale are substituted,
+ * The new response message is initialized with the same "version-number",
+ * "request-id", "attributes-charset", and "attributes-natural-language" as the
+ * provided request message. If the "attributes-charset" or
+ * "attributes-natural-language" attributes are missing from the request,
+ * 'utf-8' and a value derived from the current locale are substituted,
* respectively.
*
* @since CUPS 1.7/macOS 10.9@
@@ -3706,7 +3727,7 @@ ippReadIO(void *src, /* I - Data source */
* 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)@.
+ * @code ippGetCount(attr)@.
*
* @since CUPS 1.6/macOS 10.8@
*/
@@ -3748,7 +3769,7 @@ ippSetBoolean(ipp_t *ipp, /* I - IPP message */
* 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)@.
+ * @code ippGetCount(attr)@.
*
* @since CUPS 1.6/macOS 10.8@
*/
@@ -3789,7 +3810,7 @@ ippSetCollection(
/*
- * 'ippSetDate()' - Set a date value in an attribute.
+ * 'ippSetDate()' - Set a dateTime value in an attribute.
*
* The @code ipp@ parameter refers to an IPP message previously created using
* the @link ippNew@, @link ippNewRequest@, or @link ippNewResponse@ functions.
@@ -3797,7 +3818,7 @@ ippSetCollection(
* 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)@.
+ * @code ippGetCount(attr)@.
*
* @since CUPS 1.6/macOS 10.8@
*/
@@ -3806,7 +3827,7 @@ int /* O - 1 on success, 0 on failure */
ippSetDate(ipp_t *ipp, /* I - IPP message */
ipp_attribute_t **attr, /* IO - IPP attribute */
int element, /* I - Value number (0-based) */
- const ipp_uchar_t *datevalue)/* I - Date value */
+ const ipp_uchar_t *datevalue)/* I - dateTime value */
{
_ipp_value_t *value; /* Current value */
@@ -3854,7 +3875,7 @@ ippSetGroupTag(
ipp_tag_t group_tag) /* I - Group tag */
{
/*
- * Range check input - group tag must be 0x01 to 0x0F, per RFC 2911...
+ * Range check input - group tag must be 0x01 to 0x0F, per RFC 8011...
*/
if (!ipp || !attr || !*attr ||
@@ -3881,7 +3902,7 @@ ippSetGroupTag(
* 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)@.
+ * @code ippGetCount(attr)@.
*
* @since CUPS 1.6/macOS 10.8@
*/
@@ -3966,7 +3987,7 @@ ippSetName(ipp_t *ipp, /* I - IPP message */
* 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)@.
+ * @code ippGetCount(attr)@.
*
* @since CUPS 1.7/macOS 10.9@
*/
@@ -4084,7 +4105,7 @@ ippSetOperation(ipp_t *ipp, /* I - IPP request message */
* 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)@.
+ * @code ippGetCount(attr)@.
*
* @since CUPS 1.6/macOS 10.8@
*/
@@ -4164,7 +4185,7 @@ ippSetRequestId(ipp_t *ipp, /* I - IPP message */
* 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)@.
+ * @code ippGetCount(attr)@.
*
* @since CUPS 1.6/macOS 10.8@
*/
@@ -4272,7 +4293,7 @@ ippSetStatusCode(ipp_t *ipp, /* I - IPP response or event message */
* 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)@.
+ * @code ippGetCount(attr)@.
*
* @since CUPS 1.6/macOS 10.8@
*/
@@ -4334,7 +4355,7 @@ ippSetString(ipp_t *ipp, /* I - IPP message */
* 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)@.
+ * @code ippGetCount(attr)@.
*
* The @code format@ parameter uses formatting characters compatible with the
* printf family of standard functions. Additional arguments follow it as
@@ -4372,7 +4393,7 @@ ippSetStringf(ipp_t *ipp, /* I - IPP message */
* 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)@.
+ * @code ippGetCount(attr)@.
*
* The @code format@ parameter uses formatting characters compatible with the
* printf family of standard functions. Additional arguments follow it as
@@ -4715,19 +4736,19 @@ ippSetVersion(ipp_t *ipp, /* I - IPP message */
/*
- * 'ippTimeToDate()' - Convert from UNIX time to RFC 1903 format.
+ * 'ippTimeToDate()' - Convert from time in seconds to RFC 2579 format.
*/
-const ipp_uchar_t * /* O - RFC-1903 date/time data */
-ippTimeToDate(time_t t) /* I - UNIX time value */
+const ipp_uchar_t * /* O - RFC-2579 date/time data */
+ippTimeToDate(time_t t) /* I - Time in seconds */
{
struct tm *unixdate; /* UNIX unixdate/time info */
ipp_uchar_t *date = _cupsGlobals()->ipp_date;
- /* RFC-1903 date/time data */
+ /* RFC-2579 date/time data */
/*
- * RFC-1903 date/time format is:
+ * RFC-2579 date/time format is:
*
* Byte(s) Description
* ------- -----------
@@ -4767,7 +4788,7 @@ ippTimeToDate(time_t t) /* I - UNIX time value */
*
* This function validates the contents of an attribute based on the name and
* value tag. 1 is returned if the attribute is valid, 0 otherwise. On
- * failure, cupsLastErrorString() is set to a human-readable message.
+ * failure, @link cupsLastErrorString@ is set to a human-readable message.
*
* @since CUPS 1.7/macOS 10.9@
*/
@@ -4823,7 +4844,7 @@ ippValidateAttribute(
{
ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST,
_("\"%s\": Bad attribute name - invalid character "
- "(RFC 2911 section 4.1.3)."), attr->name);
+ "(RFC 8011 section 5.1.4)."), attr->name);
return (0);
}
@@ -4831,7 +4852,7 @@ ippValidateAttribute(
{
ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST,
_("\"%s\": Bad attribute name - bad length %d "
- "(RFC 2911 section 4.1.3)."), attr->name,
+ "(RFC 8011 section 5.1.4)."), attr->name,
(int)(ptr - attr->name));
return (0);
}
@@ -4849,7 +4870,7 @@ ippValidateAttribute(
{
ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST,
_("\"%s\": Bad boolen value %d "
- "(RFC 2911 section 4.1.11)."), attr->name,
+ "(RFC 8011 section 5.1.21)."), attr->name,
attr->values[i].boolean);
return (0);
}
@@ -4863,7 +4884,7 @@ ippValidateAttribute(
{
ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST,
_("\"%s\": Bad enum value %d - out of range "
- "(RFC 2911 section 4.1.4)."), attr->name,
+ "(RFC 8011 section 5.1.5)."), attr->name,
attr->values[i].integer);
return (0);
}
@@ -4877,7 +4898,7 @@ ippValidateAttribute(
{
ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST,
_("\"%s\": Bad octetString value - bad length %d "
- "(RFC 2911 section 4.1.10)."), attr->name,
+ "(RFC 8011 section 5.1.20)."), attr->name,
attr->values[i].unknown.length);
return (0);
}
@@ -4893,7 +4914,7 @@ ippValidateAttribute(
{
ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST,
_("\"%s\": Bad dateTime month %u "
- "(RFC 2911 section 4.1.14)."), attr->name, date[2]);
+ "(RFC 8011 section 5.1.15)."), attr->name, date[2]);
return (0);
}
@@ -4901,7 +4922,7 @@ ippValidateAttribute(
{
ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST,
_("\"%s\": Bad dateTime day %u "
- "(RFC 2911 section 4.1.14)."), attr->name, date[3]);
+ "(RFC 8011 section 5.1.15)."), attr->name, date[3]);
return (0);
}
@@ -4909,7 +4930,7 @@ ippValidateAttribute(
{
ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST,
_("\"%s\": Bad dateTime hours %u "
- "(RFC 2911 section 4.1.14)."), attr->name, date[4]);
+ "(RFC 8011 section 5.1.15)."), attr->name, date[4]);
return (0);
}
@@ -4917,7 +4938,7 @@ ippValidateAttribute(
{
ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST,
_("\"%s\": Bad dateTime minutes %u "
- "(RFC 2911 section 4.1.14)."), attr->name, date[5]);
+ "(RFC 8011 section 5.1.15)."), attr->name, date[5]);
return (0);
}
@@ -4925,7 +4946,7 @@ ippValidateAttribute(
{
ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST,
_("\"%s\": Bad dateTime seconds %u "
- "(RFC 2911 section 4.1.14)."), attr->name, date[6]);
+ "(RFC 8011 section 5.1.15)."), attr->name, date[6]);
return (0);
}
@@ -4933,7 +4954,7 @@ ippValidateAttribute(
{
ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST,
_("\"%s\": Bad dateTime deciseconds %u "
- "(RFC 2911 section 4.1.14)."), attr->name, date[7]);
+ "(RFC 8011 section 5.1.15)."), attr->name, date[7]);
return (0);
}
@@ -4941,7 +4962,7 @@ ippValidateAttribute(
{
ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST,
_("\"%s\": Bad dateTime UTC sign '%c' "
- "(RFC 2911 section 4.1.14)."), attr->name, date[8]);
+ "(RFC 8011 section 5.1.15)."), attr->name, date[8]);
return (0);
}
@@ -4949,7 +4970,7 @@ ippValidateAttribute(
{
ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST,
_("\"%s\": Bad dateTime UTC hours %u "
- "(RFC 2911 section 4.1.14)."), attr->name, date[9]);
+ "(RFC 8011 section 5.1.15)."), attr->name, date[9]);
return (0);
}
@@ -4957,7 +4978,7 @@ ippValidateAttribute(
{
ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST,
_("\"%s\": Bad dateTime UTC minutes %u "
- "(RFC 2911 section 4.1.14)."), attr->name, date[10]);
+ "(RFC 8011 section 5.1.15)."), attr->name, date[10]);
return (0);
}
}
@@ -4971,7 +4992,7 @@ ippValidateAttribute(
ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST,
_("\"%s\": Bad resolution value %dx%d%s - cross "
"feed resolution must be positive "
- "(RFC 2911 section 4.1.15)."), attr->name,
+ "(RFC 8011 section 5.1.16)."), attr->name,
attr->values[i].resolution.xres,
attr->values[i].resolution.yres,
attr->values[i].resolution.units ==
@@ -4986,7 +5007,7 @@ ippValidateAttribute(
ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST,
_("\"%s\": Bad resolution value %dx%d%s - feed "
"resolution must be positive "
- "(RFC 2911 section 4.1.15)."), attr->name,
+ "(RFC 8011 section 5.1.16)."), attr->name,
attr->values[i].resolution.xres,
attr->values[i].resolution.yres,
attr->values[i].resolution.units ==
@@ -5001,7 +5022,7 @@ ippValidateAttribute(
{
ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST,
_("\"%s\": Bad resolution value %dx%d%s - bad "
- "units value (RFC 2911 section 4.1.15)."),
+ "units value (RFC 8011 section 5.1.16)."),
attr->name, attr->values[i].resolution.xres,
attr->values[i].resolution.yres,
attr->values[i].resolution.units ==
@@ -5020,7 +5041,7 @@ ippValidateAttribute(
{
ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST,
_("\"%s\": Bad rangeOfInteger value %d-%d - lower "
- "greater than upper (RFC 2911 section 4.1.13)."),
+ "greater than upper (RFC 8011 section 5.1.14)."),
attr->name, attr->values[i].range.lower,
attr->values[i].range.upper);
return (0);
@@ -5082,7 +5103,7 @@ ippValidateAttribute(
{
ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST,
_("\"%s\": Bad text value \"%s\" - bad UTF-8 "
- "sequence (RFC 2911 section 4.1.1)."), attr->name,
+ "sequence (RFC 8011 section 5.1.2)."), attr->name,
attr->values[i].string.text);
return (0);
}
@@ -5091,7 +5112,7 @@ ippValidateAttribute(
{
ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST,
_("\"%s\": Bad text value \"%s\" - bad length %d "
- "(RFC 2911 section 4.1.1)."), attr->name,
+ "(RFC 8011 section 5.1.2)."), attr->name,
attr->values[i].string.text,
(int)(ptr - attr->values[i].string.text));
return (0);
@@ -5140,7 +5161,7 @@ ippValidateAttribute(
{
ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST,
_("\"%s\": Bad name value \"%s\" - bad UTF-8 "
- "sequence (RFC 2911 section 4.1.2)."), attr->name,
+ "sequence (RFC 8011 section 5.1.3)."), attr->name,
attr->values[i].string.text);
return (0);
}
@@ -5149,7 +5170,7 @@ ippValidateAttribute(
{
ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST,
_("\"%s\": Bad name value \"%s\" - bad length %d "
- "(RFC 2911 section 4.1.2)."), attr->name,
+ "(RFC 8011 section 5.1.3)."), attr->name,
attr->values[i].string.text,
(int)(ptr - attr->values[i].string.text));
return (0);
@@ -5169,7 +5190,7 @@ ippValidateAttribute(
{
ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST,
_("\"%s\": Bad keyword value \"%s\" - invalid "
- "character (RFC 2911 section 4.1.3)."),
+ "character (RFC 8011 section 5.1.4)."),
attr->name, attr->values[i].string.text);
return (0);
}
@@ -5178,7 +5199,7 @@ ippValidateAttribute(
{
ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST,
_("\"%s\": Bad keyword value \"%s\" - bad "
- "length %d (RFC 2911 section 4.1.3)."),
+ "length %d (RFC 8011 section 5.1.4)."),
attr->name, attr->values[i].string.text,
(int)(ptr - attr->values[i].string.text));
return (0);
@@ -5200,7 +5221,7 @@ ippValidateAttribute(
{
ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST,
_("\"%s\": Bad URI value \"%s\" - %s "
- "(RFC 2911 section 4.1.5)."), attr->name,
+ "(RFC 8011 section 5.1.6)."), attr->name,
attr->values[i].string.text,
uri_status_strings[uri_status -
HTTP_URI_STATUS_OVERFLOW]);
@@ -5211,7 +5232,7 @@ ippValidateAttribute(
{
ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST,
_("\"%s\": Bad URI value \"%s\" - bad length %d "
- "(RFC 2911 section 4.1.5)."), attr->name,
+ "(RFC 8011 section 5.1.6)."), attr->name,
attr->values[i].string.text,
(int)strlen(attr->values[i].string.text));
}
@@ -5234,7 +5255,7 @@ ippValidateAttribute(
{
ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST,
_("\"%s\": Bad uriScheme value \"%s\" - bad "
- "characters (RFC 2911 section 4.1.6)."),
+ "characters (RFC 8011 section 5.1.7)."),
attr->name, attr->values[i].string.text);
return (0);
}
@@ -5243,7 +5264,7 @@ ippValidateAttribute(
{
ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST,
_("\"%s\": Bad uriScheme value \"%s\" - bad "
- "length %d (RFC 2911 section 4.1.6)."),
+ "length %d (RFC 8011 section 5.1.7)."),
attr->name, attr->values[i].string.text,
(int)(ptr - attr->values[i].string.text));
return (0);
@@ -5263,7 +5284,7 @@ ippValidateAttribute(
{
ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST,
_("\"%s\": Bad charset value \"%s\" - bad "
- "characters (RFC 2911 section 4.1.7)."),
+ "characters (RFC 8011 section 5.1.8)."),
attr->name, attr->values[i].string.text);
return (0);
}
@@ -5272,7 +5293,7 @@ ippValidateAttribute(
{
ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST,
_("\"%s\": Bad charset value \"%s\" - bad "
- "length %d (RFC 2911 section 4.1.7)."),
+ "length %d (RFC 8011 section 5.1.8)."),
attr->name, attr->values[i].string.text,
(int)(ptr - attr->values[i].string.text));
return (0);
@@ -5318,7 +5339,7 @@ ippValidateAttribute(
{
ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST,
_("\"%s\": Bad naturalLanguage value \"%s\" - bad "
- "characters (RFC 2911 section 4.1.8)."),
+ "characters (RFC 8011 section 5.1.9)."),
attr->name, attr->values[i].string.text);
regfree(&re);
return (0);
@@ -5328,7 +5349,7 @@ ippValidateAttribute(
{
ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST,
_("\"%s\": Bad naturalLanguage value \"%s\" - bad "
- "length %d (RFC 2911 section 4.1.8)."),
+ "length %d (RFC 8011 section 5.1.9)."),
attr->name, attr->values[i].string.text,
(int)strlen(attr->values[i].string.text));
regfree(&re);
@@ -5372,7 +5393,7 @@ ippValidateAttribute(
{
ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST,
_("\"%s\": Bad mimeMediaType value \"%s\" - bad "
- "characters (RFC 2911 section 4.1.9)."),
+ "characters (RFC 8011 section 5.1.10)."),
attr->name, attr->values[i].string.text);
regfree(&re);
return (0);
@@ -5382,7 +5403,7 @@ ippValidateAttribute(
{
ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST,
_("\"%s\": Bad mimeMediaType value \"%s\" - bad "
- "length %d (RFC 2911 section 4.1.9)."),
+ "length %d (RFC 8011 section 5.1.10)."),
attr->name, attr->values[i].string.text,
(int)strlen(attr->values[i].string.text));
regfree(&re);
@@ -5405,8 +5426,8 @@ ippValidateAttribute(
* 'ippValidateAttributes()' - Validate all attributes in an IPP message.
*
* This function validates the contents of the IPP message, including each
- * attribute. Like @link ippValidateAttribute@, cupsLastErrorString() is set
- * to a human-readable message on failure.
+ * attribute. Like @link ippValidateAttribute@, @link cupsLastErrorString@ is
+ * set to a human-readable message on failure.
*
* @since CUPS 1.7/macOS 10.9@
*/
@@ -6402,6 +6423,8 @@ ipp_add_attr(ipp_t *ipp, /* I - IPP message */
* Initialize attribute...
*/
+ DEBUG_printf(("4debug_alloc: %p %s %s%s (%d values)", (void *)attr, name, num_values > 1 ? "1setOf " : "", ippTagString(value_tag), num_values));
+
if (name)
attr->name = _cupsStrAlloc(name);
@@ -6958,6 +6981,9 @@ ipp_set_value(ipp_t *ipp, /* IO - IPP message */
* Reset pointers in the list...
*/
+ DEBUG_printf(("4debug_free: %p %s", (void *)*attr, temp->name));
+ DEBUG_printf(("4debug_alloc: %p %s %s%s (%d)", (void *)temp, temp->name, temp->num_values > 1 ? "1setOf " : "", ippTagString(temp->value_tag), temp->num_values));
+
if (ipp->current == *attr && ipp->prev)
{
/*
diff --git a/cups/ipp.h b/cups/ipp.h
index 54d9d4bd..2a4f546c 100644
--- a/cups/ipp.h
+++ b/cups/ipp.h
@@ -1,7 +1,7 @@
/*
* Internet Printing Protocol definitions for CUPS.
*
- * Copyright 2007-2014 by Apple Inc.
+ * Copyright 2007-2017 by Apple Inc.
* Copyright 1997-2006 by Easy Software Products.
*
* These coded instructions, statements, and computer programs are the
@@ -77,7 +77,7 @@ extern "C" {
* Types and structures...
*/
-typedef enum ipp_dstate_e /**** Document states ****/
+typedef enum ipp_dstate_e /**** Document states @exclude all@ ****/
{
IPP_DOCUMENT_PENDING = 3, /* Document is pending */
IPP_DOCUMENT_PROCESSING = 5, /* Document is processing */
@@ -94,10 +94,10 @@ typedef enum ipp_dstate_e /**** Document states ****/
# endif /* !_CUPS_NO_DEPRECATED */
} ipp_dstate_t;
-typedef enum ipp_finishings_e /**** Finishings ****/
+typedef enum ipp_finishings_e /**** Finishings values ****/
{
IPP_FINISHINGS_NONE = 3, /* No finishing */
- IPP_FINISHINGS_STAPLE, /* Staple (any location) */
+ IPP_FINISHINGS_STAPLE, /* Staple (any location/method) */
IPP_FINISHINGS_PUNCH, /* Punch (any location/count) */
IPP_FINISHINGS_COVER, /* Add cover */
IPP_FINISHINGS_BIND, /* Bind */
@@ -169,38 +169,38 @@ typedef enum ipp_finishings_e /**** Finishings ****/
/* CUPS extensions for finishings (pre-standard versions of values above) */
IPP_FINISHINGS_CUPS_PUNCH_TOP_LEFT = 0x40000046,
- /* Punch 1 hole top left */
- IPP_FINISHINGS_CUPS_PUNCH_BOTTOM_LEFT,/* Punch 1 hole bottom left */
- IPP_FINISHINGS_CUPS_PUNCH_TOP_RIGHT, /* Punch 1 hole top right */
+ /* Punch 1 hole top left @exclude all@ */
+ IPP_FINISHINGS_CUPS_PUNCH_BOTTOM_LEFT,/* Punch 1 hole bottom left @exclude all@ */
+ IPP_FINISHINGS_CUPS_PUNCH_TOP_RIGHT, /* Punch 1 hole top right @exclude all@ */
IPP_FINISHINGS_CUPS_PUNCH_BOTTOM_RIGHT,
- /* Punch 1 hole bottom right */
- IPP_FINISHINGS_CUPS_PUNCH_DUAL_LEFT, /* Punch 2 holes left side */
- IPP_FINISHINGS_CUPS_PUNCH_DUAL_TOP, /* Punch 2 holes top edge */
- IPP_FINISHINGS_CUPS_PUNCH_DUAL_RIGHT, /* Punch 2 holes right side */
- IPP_FINISHINGS_CUPS_PUNCH_DUAL_BOTTOM,/* Punch 2 holes bottom edge */
- IPP_FINISHINGS_CUPS_PUNCH_TRIPLE_LEFT,/* Punch 3 holes left side */
- IPP_FINISHINGS_CUPS_PUNCH_TRIPLE_TOP, /* Punch 3 holes top edge */
+ /* Punch 1 hole bottom right @exclude all@ */
+ IPP_FINISHINGS_CUPS_PUNCH_DUAL_LEFT, /* Punch 2 holes left side @exclude all@ */
+ IPP_FINISHINGS_CUPS_PUNCH_DUAL_TOP, /* Punch 2 holes top edge @exclude all@ */
+ IPP_FINISHINGS_CUPS_PUNCH_DUAL_RIGHT, /* Punch 2 holes right side @exclude all@ */
+ IPP_FINISHINGS_CUPS_PUNCH_DUAL_BOTTOM,/* Punch 2 holes bottom edge @exclude all@ */
+ IPP_FINISHINGS_CUPS_PUNCH_TRIPLE_LEFT,/* Punch 3 holes left side @exclude all@ */
+ IPP_FINISHINGS_CUPS_PUNCH_TRIPLE_TOP, /* Punch 3 holes top edge @exclude all@ */
IPP_FINISHINGS_CUPS_PUNCH_TRIPLE_RIGHT,
- /* Punch 3 holes right side */
+ /* Punch 3 holes right side @exclude all@ */
IPP_FINISHINGS_CUPS_PUNCH_TRIPLE_BOTTOM,
- /* Punch 3 holes bottom edge */
- IPP_FINISHINGS_CUPS_PUNCH_QUAD_LEFT, /* Punch 4 holes left side */
- IPP_FINISHINGS_CUPS_PUNCH_QUAD_TOP, /* Punch 4 holes top edge */
- IPP_FINISHINGS_CUPS_PUNCH_QUAD_RIGHT, /* Punch 4 holes right side */
- IPP_FINISHINGS_CUPS_PUNCH_QUAD_BOTTOM,/* Punch 4 holes bottom edge */
+ /* Punch 3 holes bottom edge @exclude all@ */
+ IPP_FINISHINGS_CUPS_PUNCH_QUAD_LEFT, /* Punch 4 holes left side @exclude all@ */
+ IPP_FINISHINGS_CUPS_PUNCH_QUAD_TOP, /* Punch 4 holes top edge @exclude all@ */
+ IPP_FINISHINGS_CUPS_PUNCH_QUAD_RIGHT, /* Punch 4 holes right side @exclude all@ */
+ IPP_FINISHINGS_CUPS_PUNCH_QUAD_BOTTOM,/* Punch 4 holes bottom edge @exclude all@ */
IPP_FINISHINGS_CUPS_FOLD_ACCORDIAN = 0x4000005A,
- /* Accordian-fold the paper vertically into four sections */
- IPP_FINISHINGS_CUPS_FOLD_DOUBLE_GATE, /* Fold the top and bottom quarters of the paper towards the midline, then fold in half vertically */
- IPP_FINISHINGS_CUPS_FOLD_GATE, /* Fold the top and bottom quarters of the paper towards the midline */
- IPP_FINISHINGS_CUPS_FOLD_HALF, /* Fold the paper in half vertically */
- IPP_FINISHINGS_CUPS_FOLD_HALF_Z, /* Fold the paper in half horizontally, then Z-fold the paper vertically */
- IPP_FINISHINGS_CUPS_FOLD_LEFT_GATE, /* Fold the top quarter of the paper towards the midline */
- IPP_FINISHINGS_CUPS_FOLD_LETTER, /* Fold the paper into three sections vertically; sometimes also known as a C fold*/
- IPP_FINISHINGS_CUPS_FOLD_PARALLEL, /* Fold the paper in half vertically two times, yielding four sections */
- IPP_FINISHINGS_CUPS_FOLD_POSTER, /* Fold the paper in half horizontally and vertically; sometimes also called a cross fold */
- IPP_FINISHINGS_CUPS_FOLD_RIGHT_GATE, /* Fold the bottom quarter of the paper towards the midline */
- IPP_FINISHINGS_CUPS_FOLD_Z /* Fold the paper vertically into three sections, forming a Z */
+ /* Accordian-fold the paper vertically into four sections @exclude all@ */
+ IPP_FINISHINGS_CUPS_FOLD_DOUBLE_GATE, /* Fold the top and bottom quarters of the paper towards the midline, then fold in half vertically @exclude all@ */
+ IPP_FINISHINGS_CUPS_FOLD_GATE, /* Fold the top and bottom quarters of the paper towards the midline @exclude all@ */
+ IPP_FINISHINGS_CUPS_FOLD_HALF, /* Fold the paper in half vertically @exclude all@ */
+ IPP_FINISHINGS_CUPS_FOLD_HALF_Z, /* Fold the paper in half horizontally, then Z-fold the paper vertically @exclude all@ */
+ IPP_FINISHINGS_CUPS_FOLD_LEFT_GATE, /* Fold the top quarter of the paper towards the midline @exclude all@ */
+ IPP_FINISHINGS_CUPS_FOLD_LETTER, /* Fold the paper into three sections vertically; sometimes also known as a C fold @exclude all@ */
+ IPP_FINISHINGS_CUPS_FOLD_PARALLEL, /* Fold the paper in half vertically two times, yielding four sections @exclude all@ */
+ IPP_FINISHINGS_CUPS_FOLD_POSTER, /* Fold the paper in half horizontally and vertically; sometimes also called a cross fold @exclude all@ */
+ IPP_FINISHINGS_CUPS_FOLD_RIGHT_GATE, /* Fold the bottom quarter of the paper towards the midline @exclude all@ */
+ IPP_FINISHINGS_CUPS_FOLD_Z /* Fold the paper vertically into three sections, forming a Z @exclude all@ */
} ipp_finishings_t;
# ifndef _CUPS_NO_DEPRECATED
# define IPP_FINISHINGS_JOB_OFFSET IPP_FINISHINGS_JOG_OFFSET
@@ -208,7 +208,7 @@ typedef enum ipp_finishings_e /**** Finishings ****/
typedef enum ipp_finishings_e ipp_finish_t;
# endif /* !_CUPS_NO_DEPRECATED */
-typedef enum ipp_jcollate_e /**** Job collation types ****/
+typedef enum ipp_jcollate_e /**** Job collation types @deprecated@ @exclude all@ ****/
{
IPP_JCOLLATE_UNCOLLATED_SHEETS = 3,
IPP_JCOLLATE_COLLATED_DOCUMENTS,
@@ -248,98 +248,98 @@ typedef enum ipp_op_e /**** IPP operations ****/
{
IPP_OP_CUPS_INVALID = -1, /* Invalid operation name for @link ippOpValue@ */
IPP_OP_CUPS_NONE = 0, /* No operation @private@ */
- IPP_OP_PRINT_JOB = 0x0002, /* Print a single file */
- IPP_OP_PRINT_URI, /* Print a single URL */
- IPP_OP_VALIDATE_JOB, /* Validate job options */
- IPP_OP_CREATE_JOB, /* Create an empty print job */
- IPP_OP_SEND_DOCUMENT, /* Add a file to a job */
- IPP_OP_SEND_URI, /* Add a URL to a job */
- IPP_OP_CANCEL_JOB, /* Cancel a job */
- IPP_OP_GET_JOB_ATTRIBUTES, /* Get job attributes */
- IPP_OP_GET_JOBS, /* Get a list of jobs */
- IPP_OP_GET_PRINTER_ATTRIBUTES, /* Get printer attributes */
- IPP_OP_HOLD_JOB, /* Hold a job for printing */
- IPP_OP_RELEASE_JOB, /* Release a job for printing */
- IPP_OP_RESTART_JOB, /* Reprint a job */
- IPP_OP_PAUSE_PRINTER = 0x0010, /* Stop a printer */
- IPP_OP_RESUME_PRINTER, /* Start a printer */
- IPP_OP_PURGE_JOBS, /* Cancel all jobs */
- IPP_OP_SET_PRINTER_ATTRIBUTES, /* Set printer attributes */
- IPP_OP_SET_JOB_ATTRIBUTES, /* Set job attributes */
- IPP_OP_GET_PRINTER_SUPPORTED_VALUES, /* Get supported attribute values */
- IPP_OP_CREATE_PRINTER_SUBSCRIPTIONS, /* Create one or more printer subscriptions @since CUPS 1.2/macOS 10.5@ */
- IPP_OP_CREATE_JOB_SUBSCRIPTIONS, /* Create one of more job subscriptions @since CUPS 1.2/macOS 10.5@ */
- IPP_OP_GET_SUBSCRIPTION_ATTRIBUTES, /* Get subscription attributes @since CUPS 1.2/macOS 10.5@ */
- IPP_OP_GET_SUBSCRIPTIONS, /* Get list of subscriptions @since CUPS 1.2/macOS 10.5@ */
- IPP_OP_RENEW_SUBSCRIPTION, /* Renew a printer subscription @since CUPS 1.2/macOS 10.5@ */
- IPP_OP_CANCEL_SUBSCRIPTION, /* Cancel a subscription @since CUPS 1.2/macOS 10.5@ */
- IPP_OP_GET_NOTIFICATIONS, /* Get notification events @since CUPS 1.2/macOS 10.5@ */
- IPP_OP_SEND_NOTIFICATIONS, /* Send notification events @private@ */
- IPP_OP_GET_RESOURCE_ATTRIBUTES, /* Get resource attributes @private@ */
- IPP_OP_GET_RESOURCE_DATA, /* Get resource data @private@ */
- IPP_OP_GET_RESOURCES, /* Get list of resources @private@ */
- IPP_OP_GET_PRINT_SUPPORT_FILES, /* Get printer support files @private@ */
- IPP_OP_ENABLE_PRINTER, /* Start a printer */
- IPP_OP_DISABLE_PRINTER, /* Stop a printer */
+ IPP_OP_PRINT_JOB = 0x0002, /* Print-Job: Print a single file */
+ IPP_OP_PRINT_URI, /* Print-URI: Print a single URL @exclude all@ */
+ IPP_OP_VALIDATE_JOB, /* Validate-Job: Validate job values prior to submission */
+ IPP_OP_CREATE_JOB, /* Create-Job: Create an empty print job */
+ IPP_OP_SEND_DOCUMENT, /* Send-Document: Add a file to a job */
+ IPP_OP_SEND_URI, /* Send-URI: Add a URL to a job @exclude all@ */
+ IPP_OP_CANCEL_JOB, /* Cancel-Job: Cancel a job */
+ IPP_OP_GET_JOB_ATTRIBUTES, /* Get-Job-Attribute: Get information about a job */
+ IPP_OP_GET_JOBS, /* Get-Jobs: Get a list of jobs */
+ IPP_OP_GET_PRINTER_ATTRIBUTES, /* Get-Printer-Attributes: Get information about a printer */
+ IPP_OP_HOLD_JOB, /* Hold-Job: Hold a job for printing */
+ IPP_OP_RELEASE_JOB, /* Release-Job: Release a job for printing */
+ IPP_OP_RESTART_JOB, /* Restart-Job: Reprint a job @deprecated@ */
+ IPP_OP_PAUSE_PRINTER = 0x0010, /* Pause-Printer: Stop a printer */
+ IPP_OP_RESUME_PRINTER, /* Resume-Printer: Start a printer */
+ IPP_OP_PURGE_JOBS, /* Purge-Jobs: Delete all jobs @deprecated@ @exclude all@ */
+ IPP_OP_SET_PRINTER_ATTRIBUTES, /* Set-Printer-Attributes: Set printer values */
+ IPP_OP_SET_JOB_ATTRIBUTES, /* Set-Job-Attributes: Set job values */
+ IPP_OP_GET_PRINTER_SUPPORTED_VALUES, /* Get-Printer-Supported-Values: Get supported values */
+ IPP_OP_CREATE_PRINTER_SUBSCRIPTIONS, /* Create-Printer-Subscriptions: Create one or more printer subscriptions @since CUPS 1.2/macOS 10.5@ */
+ IPP_OP_CREATE_JOB_SUBSCRIPTIONS, /* Create-Job-Subscriptions: Create one of more job subscriptions @since CUPS 1.2/macOS 10.5@ */
+ IPP_OP_GET_SUBSCRIPTION_ATTRIBUTES, /* Get-Subscription-Attributes: Get subscription information @since CUPS 1.2/macOS 10.5@ */
+ IPP_OP_GET_SUBSCRIPTIONS, /* Get-Subscriptions: Get list of subscriptions @since CUPS 1.2/macOS 10.5@ */
+ IPP_OP_RENEW_SUBSCRIPTION, /* Renew-Subscription: Renew a printer subscription @since CUPS 1.2/macOS 10.5@ */
+ IPP_OP_CANCEL_SUBSCRIPTION, /* Cancel-Subscription: Cancel a subscription @since CUPS 1.2/macOS 10.5@ */
+ IPP_OP_GET_NOTIFICATIONS, /* Get-Notifications: Get notification events @since CUPS 1.2/macOS 10.5@ */
+ IPP_OP_SEND_NOTIFICATIONS, /* Send-Notifications: Send notification events @private@ */
+ IPP_OP_GET_RESOURCE_ATTRIBUTES, /* Get-Resource-Attributes: Get resource information @private@ */
+ IPP_OP_GET_RESOURCE_DATA, /* Get-Resource-Data: Get resource data @private@ @deprecated@ */
+ IPP_OP_GET_RESOURCES, /* Get-Resources: Get list of resources @private@ */
+ IPP_OP_GET_PRINT_SUPPORT_FILES, /* Get-Printer-Support-Files: Get printer support files @private@ */
+ IPP_OP_ENABLE_PRINTER, /* Enable-Printer: Accept new jobs for a printer */
+ IPP_OP_DISABLE_PRINTER, /* Disable-Printer: Reject new jobs for a printer */
IPP_OP_PAUSE_PRINTER_AFTER_CURRENT_JOB,
- /* Stop printer after the current job */
- IPP_OP_HOLD_NEW_JOBS, /* Hold new jobs */
- IPP_OP_RELEASE_HELD_NEW_JOBS, /* Release new jobs */
- IPP_OP_DEACTIVATE_PRINTER, /* Stop a printer */
- IPP_OP_ACTIVATE_PRINTER, /* Start a printer */
- IPP_OP_RESTART_PRINTER, /* Restart a printer */
- IPP_OP_SHUTDOWN_PRINTER, /* Turn a printer off */
- IPP_OP_STARTUP_PRINTER, /* Turn a printer on */
- IPP_OP_REPROCESS_JOB, /* Reprint a job */
- IPP_OP_CANCEL_CURRENT_JOB, /* Cancel the current job */
- IPP_OP_SUSPEND_CURRENT_JOB, /* Suspend the current job */
- IPP_OP_RESUME_JOB, /* Resume the current job */
- IPP_OP_PROMOTE_JOB, /* Promote a job to print sooner */
- IPP_OP_SCHEDULE_JOB_AFTER, /* Schedule a job to print after another */
- IPP_OP_CANCEL_DOCUMENT = 0x0033, /* Cancel-Document */
- IPP_OP_GET_DOCUMENT_ATTRIBUTES, /* Get-Document-Attributes */
- IPP_OP_GET_DOCUMENTS, /* Get-Documents */
- IPP_OP_DELETE_DOCUMENT, /* Delete-Document */
- IPP_OP_SET_DOCUMENT_ATTRIBUTES, /* Set-Document-Attributes */
- IPP_OP_CANCEL_JOBS, /* Cancel-Jobs */
- IPP_OP_CANCEL_MY_JOBS, /* Cancel-My-Jobs */
- IPP_OP_RESUBMIT_JOB, /* Resubmit-Job */
- IPP_OP_CLOSE_JOB, /* Close-Job */
- IPP_OP_IDENTIFY_PRINTER, /* Identify-Printer */
- IPP_OP_VALIDATE_DOCUMENT, /* Validate-Document */
- IPP_OP_ADD_DOCUMENT_IMAGES, /* Add-Document-Images */
- IPP_OP_ACKNOWLEDGE_DOCUMENT, /* Acknowledge-Document */
- IPP_OP_ACKNOWLEDGE_IDENTIFY_PRINTER, /* Acknowledge-Identify-Printer */
- IPP_OP_ACKNOWLEDGE_JOB, /* Acknowledge-Job */
- IPP_OP_FETCH_DOCUMENT, /* Fetch-Document */
- IPP_OP_FETCH_JOB, /* Fetch-Job */
- IPP_OP_GET_OUTPUT_DEVICE_ATTRIBUTES, /* Get-Output-Device-Attributes */
- IPP_OP_UPDATE_ACTIVE_JOBS, /* Update-Active-Jobs */
- IPP_OP_DEREGISTER_OUTPUT_DEVICE, /* Deregister-Output-Device */
- IPP_OP_UPDATE_DOCUMENT_STATUS, /* Update-Document-Status */
- IPP_OP_UPDATE_JOB_STATUS, /* Update-Job-Status */
+ /* Pause-Printer-After-Current-Job: Stop printer after the current job */
+ IPP_OP_HOLD_NEW_JOBS, /* Hold-New-Jobs: Hold new jobs */
+ IPP_OP_RELEASE_HELD_NEW_JOBS, /* Release-Held-New-Jobs: Release new jobs that were previously held */
+ IPP_OP_DEACTIVATE_PRINTER, /* Deactivate-Printer: Stop a printer and do not accept jobs @deprecated@ @exclude all@ */
+ IPP_OP_ACTIVATE_PRINTER, /* Activate-Printer: Start a printer and accept jobs @deprecated@ @exclude all@ */
+ IPP_OP_RESTART_PRINTER, /* Restart-Printer: Restart a printer @exclude all@ */
+ IPP_OP_SHUTDOWN_PRINTER, /* Shutdown-Printer: Turn a printer off @exclude all@ */
+ IPP_OP_STARTUP_PRINTER, /* Startup-Printer: Turn a printer on @exclude all@ */
+ IPP_OP_REPROCESS_JOB, /* Reprocess-Job: Reprint a job @deprecated@ @exclude all@*/
+ IPP_OP_CANCEL_CURRENT_JOB, /* Cancel-Current-Job: Cancel the current job */
+ IPP_OP_SUSPEND_CURRENT_JOB, /* Suspend-Current-Job: Suspend the current job */
+ IPP_OP_RESUME_JOB, /* Resume-Job: Resume the current job */
+ IPP_OP_PROMOTE_JOB, /* Promote-Job: Promote a job to print sooner */
+ IPP_OP_SCHEDULE_JOB_AFTER, /* Schedule-Job-After: Schedule a job to print after another */
+ IPP_OP_CANCEL_DOCUMENT = 0x0033, /* Cancel-Document: Cancel a document @exclude all@ */
+ IPP_OP_GET_DOCUMENT_ATTRIBUTES, /* Get-Document-Attributes: Get document information @exclude all@ */
+ IPP_OP_GET_DOCUMENTS, /* Get-Documents: Get a list of documents in a job @exclude all@ */
+ IPP_OP_DELETE_DOCUMENT, /* Delete-Document: Delete a document @deprecated@ @exclude all@ */
+ IPP_OP_SET_DOCUMENT_ATTRIBUTES, /* Set-Document-Attributes: Set document values @exclude all@ */
+ IPP_OP_CANCEL_JOBS, /* Cancel-Jobs: Cancel all jobs (administrative) */
+ IPP_OP_CANCEL_MY_JOBS, /* Cancel-My-Jobs: Cancel a user's jobs */
+ IPP_OP_RESUBMIT_JOB, /* Resubmit-Job: Copy and reprint a job @exclude all@ */
+ IPP_OP_CLOSE_JOB, /* Close-Job: Close a job and start printing */
+ IPP_OP_IDENTIFY_PRINTER, /* Identify-Printer: Make the printer beep, flash, or display a message for identification */
+ IPP_OP_VALIDATE_DOCUMENT, /* Validate-Document: Validate document values prior to submission @exclude all@ */
+ IPP_OP_ADD_DOCUMENT_IMAGES, /* Add-Document-Images: Add image(s) from the specified scanner source @exclude all@ */
+ IPP_OP_ACKNOWLEDGE_DOCUMENT, /* Acknowledge-Document: Acknowledge processing of a document @exclude all@ */
+ IPP_OP_ACKNOWLEDGE_IDENTIFY_PRINTER, /* Acknowledge-Identify-Printer: Acknowledge action on an Identify-Printer request @exclude all@ */
+ IPP_OP_ACKNOWLEDGE_JOB, /* Acknowledge-Job: Acknowledge processing of a job @exclude all@ */
+ IPP_OP_FETCH_DOCUMENT, /* Fetch-Document: Fetch a document for processing @exclude all@ */
+ IPP_OP_FETCH_JOB, /* Fetch-Job: Fetch a job for processing @exclude all@ */
+ IPP_OP_GET_OUTPUT_DEVICE_ATTRIBUTES, /* Get-Output-Device-Attributes: Get printer information for a specific output device @exclude all@ */
+ IPP_OP_UPDATE_ACTIVE_JOBS, /* Update-Active-Jobs: Update the list of active jobs that a proxy has processed @exclude all@ */
+ IPP_OP_DEREGISTER_OUTPUT_DEVICE, /* Deregister-Output-Device: Remove an output device @exclude all@ */
+ IPP_OP_UPDATE_DOCUMENT_STATUS, /* Update-Document-Status: Update document values @exclude all@ */
+ IPP_OP_UPDATE_JOB_STATUS, /* Update-Job-Status: Update job values @exclude all@ */
IPP_OP_UPDATE_OUTPUT_DEVICE_ATTRIBUTES,
- /* Update-Output-Device-Attributes */
- IPP_OP_GET_NEXT_DOCUMENT_DATA, /* Get-Next-Document-Data */
+ /* Update-Output-Device-Attributes: Update output device values @exclude all@ */
+ IPP_OP_GET_NEXT_DOCUMENT_DATA, /* Get-Next-Document-Data: Scan more document data @exclude all@ */
IPP_OP_PRIVATE = 0x4000, /* Reserved @private@ */
- IPP_OP_CUPS_GET_DEFAULT, /* Get the default printer */
- IPP_OP_CUPS_GET_PRINTERS, /* Get a list of printers and/or classes */
- IPP_OP_CUPS_ADD_MODIFY_PRINTER, /* Add or modify a printer */
- IPP_OP_CUPS_DELETE_PRINTER, /* Delete a printer */
- IPP_OP_CUPS_GET_CLASSES, /* Get a list of classes @deprecated@ */
- IPP_OP_CUPS_ADD_MODIFY_CLASS, /* Add or modify a class */
- IPP_OP_CUPS_DELETE_CLASS, /* Delete a class */
- IPP_OP_CUPS_ACCEPT_JOBS, /* Accept new jobs on a printer */
- IPP_OP_CUPS_REJECT_JOBS, /* Reject new jobs on a printer */
- IPP_OP_CUPS_SET_DEFAULT, /* Set the default printer */
- IPP_OP_CUPS_GET_DEVICES, /* Get a list of supported devices @deprecated@ */
- IPP_OP_CUPS_GET_PPDS, /* Get a list of supported drivers @deprecated@ */
- IPP_OP_CUPS_MOVE_JOB, /* Move a job to a different printer */
- IPP_OP_CUPS_AUTHENTICATE_JOB, /* Authenticate a job @since CUPS 1.2/macOS 10.5@ */
- IPP_OP_CUPS_GET_PPD, /* Get a PPD file @deprecated@ */
- IPP_OP_CUPS_GET_DOCUMENT = 0x4027, /* Get a document file @since CUPS 1.4/macOS 10.6@ */
- IPP_OP_CUPS_CREATE_LOCAL_PRINTER /* Create a local (temporary) printer @since CUPS 2.2 */
+ IPP_OP_CUPS_GET_DEFAULT, /* CUPS-Get-Default: Get the default printer */
+ IPP_OP_CUPS_GET_PRINTERS, /* CUPS-Get-Printers: Get a list of printers and/or classes */
+ IPP_OP_CUPS_ADD_MODIFY_PRINTER, /* CUPS-Add-Modify-Printer: Add or modify a printer */
+ IPP_OP_CUPS_DELETE_PRINTER, /* CUPS-Delete-Printer: Delete a printer */
+ IPP_OP_CUPS_GET_CLASSES, /* CUPS-Get-Classes: Get a list of classes @deprecated@ @exclude all@ */
+ IPP_OP_CUPS_ADD_MODIFY_CLASS, /* CUPS-Add-Modify-Class: Add or modify a class */
+ IPP_OP_CUPS_DELETE_CLASS, /* CUPS-Delete-Class: Delete a class */
+ IPP_OP_CUPS_ACCEPT_JOBS, /* CUPS-Accept-Jobs: Accept new jobs on a printer @exclude all@ */
+ IPP_OP_CUPS_REJECT_JOBS, /* CUPS-Reject-Jobs: Reject new jobs on a printer @exclude all@ */
+ IPP_OP_CUPS_SET_DEFAULT, /* CUPS-Set-Default: Set the default printer */
+ IPP_OP_CUPS_GET_DEVICES, /* CUPS-Get-Devices: Get a list of supported devices @deprecated@ */
+ IPP_OP_CUPS_GET_PPDS, /* CUPS-Get-PPDs: Get a list of supported drivers @deprecated@ */
+ IPP_OP_CUPS_MOVE_JOB, /* CUPS-Move-Job: Move a job to a different printer */
+ IPP_OP_CUPS_AUTHENTICATE_JOB, /* CUPS-Authenticate-Job: Authenticate a job @since CUPS 1.2/macOS 10.5@ */
+ IPP_OP_CUPS_GET_PPD, /* CUPS-Get-PPD: Get a PPD file @deprecated@ */
+ IPP_OP_CUPS_GET_DOCUMENT = 0x4027, /* CUPS-Get-Document: Get a document file @since CUPS 1.4/macOS 10.6@ */
+ IPP_OP_CUPS_CREATE_LOCAL_PRINTER /* CUPS-Create-Local-Printer: Create a local (temporary) printer @since CUPS 2.2@ */
# ifndef _CUPS_NO_DEPRECATED
# define IPP_PRINT_JOB IPP_OP_PRINT_JOB
@@ -364,7 +364,7 @@ typedef enum ipp_op_e /**** IPP operations ****/
# define IPP_CREATE_PRINTER_SUBSCRIPTION IPP_OP_CREATE_PRINTER_SUBSCRIPTIONS
# define IPP_CREATE_JOB_SUBSCRIPTION IPP_OP_CREATE_JOB_SUBSCRIPTIONS
# define IPP_OP_CREATE_PRINTER_SUBSCRIPTION IPP_OP_CREATE_PRINTER_SUBSCRIPTIONS
-# define IPP_OP_CREATE_JOB_SUBSCRIPTION IPP_OP_CREATE_JOB_SUBSCRIPTIONS
+# define IPP_OP_CREATE_JOB_SUBSCRIPTION IPP_OP_CREATE_JOB_SUBSCRIPTIONS
# define IPP_GET_SUBSCRIPTION_ATTRIBUTES IPP_OP_GET_SUBSCRIPTION_ATTRIBUTES
# define IPP_GET_SUBSCRIPTIONS IPP_OP_GET_SUBSCRIPTIONS
# define IPP_RENEW_SUBSCRIPTION IPP_OP_RENEW_SUBSCRIPTION
@@ -442,7 +442,7 @@ typedef enum ipp_orient_e /**** Orientation values ****/
# endif /* !_CUPS_NO_DEPRECATED */
} ipp_orient_t;
-typedef enum ipp_pstate_e /**** Printer states ****/
+typedef enum ipp_pstate_e /**** Printer state values ****/
{
IPP_PSTATE_IDLE = 3, /* Printer is idle */
IPP_PSTATE_PROCESSING, /* Printer is working */
@@ -455,7 +455,7 @@ typedef enum ipp_pstate_e /**** Printer states ****/
# endif /* _CUPS_NO_DEPRECATED */
} ipp_pstate_t;
-typedef enum ipp_quality_e /**** Qualities ****/
+typedef enum ipp_quality_e /**** Print quality values ****/
{
IPP_QUALITY_DRAFT = 3, /* Draft quality */
IPP_QUALITY_NORMAL, /* Normal quality */
@@ -468,7 +468,7 @@ typedef enum ipp_res_e /**** Resolution units ****/
IPP_RES_PER_CM /* Pixels per centimeter */
} ipp_res_t;
-typedef enum ipp_state_e /**** IPP states ****/
+typedef enum ipp_state_e /**** ipp_t state values ****/
{
IPP_STATE_ERROR = -1, /* An error occurred */
IPP_STATE_IDLE, /* Nothing is happening/request completed */
@@ -485,7 +485,7 @@ typedef enum ipp_state_e /**** IPP states ****/
# endif /* !_CUPS_NO_DEPRECATED */
} ipp_state_t;
-typedef enum ipp_status_e /**** IPP status codes ****/
+typedef enum ipp_status_e /**** IPP status code values ****/
{
IPP_STATUS_CUPS_INVALID = -1, /* Invalid status name for @link ippErrorValue@ */
IPP_STATUS_OK = 0x0000, /* successful-ok */
@@ -498,7 +498,7 @@ typedef enum ipp_status_e /**** IPP status codes ****/
IPP_STATUS_OK_EVENTS_COMPLETE, /* successful-ok-events-complete */
IPP_STATUS_REDIRECTION_OTHER_SITE = 0x0200,
/* redirection-other-site @private@ */
- IPP_STATUS_CUPS_SEE_OTHER = 0x0280, /* cups-see-other */
+ IPP_STATUS_CUPS_SEE_OTHER = 0x0280, /* cups-see-other @private@ */
IPP_STATUS_ERROR_BAD_REQUEST = 0x0400,/* client-error-bad-request */
IPP_STATUS_ERROR_FORBIDDEN, /* client-error-forbidden */
IPP_STATUS_ERROR_NOT_AUTHENTICATED, /* client-error-not-authenticated */
@@ -574,7 +574,7 @@ typedef enum ipp_status_e /**** IPP status codes ****/
IPP_STATUS_ERROR_CUPS_AUTHENTICATION_CANCELED = 0x1000,
/* cups-authentication-canceled - Authentication canceled by user @since CUPS 1.5/macOS 10.7@ */
IPP_STATUS_ERROR_CUPS_PKI, /* cups-pki-error - Error negotiating a secure connection @since CUPS 1.5/macOS 10.7@ */
- IPP_STATUS_ERROR_CUPS_UPGRADE_REQUIRED/* cups-upgrade-required - TLS upgrade required */
+ IPP_STATUS_ERROR_CUPS_UPGRADE_REQUIRED/* cups-upgrade-required - TLS upgrade required @since CUPS 1.5/macOS 10.7@ */
# ifndef _CUPS_NO_DEPRECATED
# define IPP_OK IPP_STATUS_OK
@@ -636,7 +636,7 @@ typedef enum ipp_status_e /**** IPP status codes ****/
# endif /* _CUPS_NO_DEPRECATED */
} ipp_status_t;
-typedef enum ipp_tag_e /**** Format tags for attributes ****/
+typedef enum ipp_tag_e /**** Value and group tag values for attributes ****/
{
IPP_TAG_CUPS_INVALID = -1, /* Invalid tag name for @link ippTagValue@ */
IPP_TAG_ZERO = 0x00, /* Zero tag - used for separators */
@@ -648,7 +648,7 @@ typedef enum ipp_tag_e /**** Format tags for attributes ****/
IPP_TAG_SUBSCRIPTION, /* Subscription group */
IPP_TAG_EVENT_NOTIFICATION, /* Event group */
IPP_TAG_RESOURCE, /* Resource group @private@ */
- IPP_TAG_DOCUMENT, /* Document group */
+ IPP_TAG_DOCUMENT, /* Document group @exclude all@ */
IPP_TAG_UNSUPPORTED_VALUE = 0x10, /* Unsupported value */
IPP_TAG_DEFAULT, /* Default value */
IPP_TAG_UNKNOWN, /* Unknown value */
@@ -663,10 +663,10 @@ typedef enum ipp_tag_e /**** Format tags for attributes ****/
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_BEGIN_COLLECTION, /* Beginning of collection value @exclude all@ */
IPP_TAG_TEXTLANG, /* Text-with-language value */
IPP_TAG_NAMELANG, /* Name-with-language value */
- IPP_TAG_END_COLLECTION, /* End of collection value */
+ IPP_TAG_END_COLLECTION, /* End of collection value @exclude all@ */
IPP_TAG_TEXT = 0x41, /* Text value */
IPP_TAG_NAME, /* Name value */
IPP_TAG_RESERVED_STRING, /* Reserved for future string value @private@ */
@@ -676,8 +676,8 @@ typedef enum ipp_tag_e /**** Format tags for attributes ****/
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_MEMBERNAME, /* Collection member name value @exclude all@ */
+ IPP_TAG_EXTENSION = 0x7f, /* Extension point for 32-bit tags @exclude all@ */
IPP_TAG_CUPS_MASK = 0x7fffffff, /* Mask for copied attribute values @private@ */
/* The following expression is used to avoid compiler warnings with +/-0x80000000 */
IPP_TAG_CUPS_CONST = -0x7fffffff-1 /* Bitflag for copied/const attribute values @private@ */
@@ -688,17 +688,18 @@ typedef enum ipp_tag_e /**** Format tags for attributes ****/
# endif /* !_CUPS_NO_DEPRECATED */
} ipp_tag_t;
-typedef unsigned char ipp_uchar_t; /**** Unsigned 8-bit integer/character ****/
+typedef unsigned char ipp_uchar_t; /**** Unsigned 8-bit integer/character @exclude all@ ****/
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/macOS 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/macOS 10.5@ ****/
+ /**** ippReadIO/ippWriteIO callback function @since CUPS 1.2/macOS 10.5@ ****/
/**** New in CUPS 1.6/macOS 10.8 ****/
typedef int (*ipp_copycb_t)(void *context, ipp_t *dst, ipp_attribute_t *attr);
+ /**** ippCopyAttributes callback function @since CUPS 1.6/macOS 10.8 ****/
/*
@@ -805,7 +806,7 @@ typedef union _ipp_value_u /**** Attribute Value ****/
} _ipp_value_t;
typedef _ipp_value_t ipp_value_t; /**** Convenience typedef that will be removed @private@ ****/
-struct _ipp_attribute_s /**** Attribute ****/
+struct _ipp_attribute_s /**** IPP attribute ****/
{
ipp_attribute_t *next; /* Next attribute in list */
ipp_tag_t group_tag, /* Job/Printer/Operation group tag */
diff --git a/cups/language.c b/cups/language.c
index f3a3496b..e6d2d44a 100644
--- a/cups/language.c
+++ b/cups/language.c
@@ -123,7 +123,9 @@ static const _apple_language_locale_t apple_language_locale[] =
{ "nb", "no" },
{ "nb_NO", "no" },
{ "zh-Hans", "zh_CN" },
+ { "zh_HANS", "zh_CN" },
{ "zh-Hant", "zh_TW" },
+ { "zh_HANT", "zh_TW" },
{ "zh-Hant_CN", "zh_TW" }
};
#endif /* __APPLE__ */
@@ -254,7 +256,15 @@ _cupsAppleLocale(CFStringRef languageName, /* I - Apple language ID */
{
int i; /* Looping var */
CFStringRef localeName; /* Locale as a CF string */
+#ifdef DEBUG
+ char temp[1024]; /* Temporary string */
+
+ if (!CFStringGetCString(languageName, temp, (CFIndex)sizeof(temp), kCFStringEncodingASCII))
+ temp[0] = '\0';
+
+ DEBUG_printf(("_cupsAppleLocale(languageName=%p(%s), locale=%p, localsize=%d)", (void *)languageName, temp, (void *)locale, (int)localesize));
+#endif /* DEBUG */
localeName = CFLocaleCreateCanonicalLocaleIdentifierFromString(kCFAllocatorDefault, languageName);
@@ -267,6 +277,8 @@ _cupsAppleLocale(CFStringRef languageName, /* I - Apple language ID */
if (!CFStringGetCString(localeName, locale, (CFIndex)localesize, kCFStringEncodingASCII))
*locale = '\0';
+ DEBUG_printf(("_cupsAppleLocale: locale=\"%s\"", locale));
+
CFRelease(localeName);
/*
@@ -278,8 +290,12 @@ _cupsAppleLocale(CFStringRef languageName, /* I - Apple language ID */
sizeof(apple_language_locale[0]));
i ++)
{
- if (!strcmp(locale, apple_language_locale[i].language))
+ size_t len = strlen(apple_language_locale[i].language);
+
+ if (!strcmp(locale, apple_language_locale[i].language) ||
+ (!strncmp(locale, apple_language_locale[i].language, len) && (locale[len] == '_' || locale[len] == '-')))
{
+ DEBUG_printf(("_cupsAppleLocale: Updating locale to \"%s\".", apple_language_locale[i].locale));
strlcpy(locale, apple_language_locale[i].locale, localesize);
break;
}
@@ -296,7 +312,10 @@ _cupsAppleLocale(CFStringRef languageName, /* I - Apple language ID */
}
if (!*locale)
+ {
+ DEBUG_puts("_cupsAppleLocale: Returning NULL.");
return (NULL);
+ }
/*
* Convert language subtag into region subtag...
@@ -304,10 +323,14 @@ _cupsAppleLocale(CFStringRef languageName, /* I - Apple language ID */
if (locale[2] == '-')
locale[2] = '_';
+ else if (locale[3] == '-')
+ locale[3] = '_';
if (!strchr(locale, '.'))
strlcat(locale, ".UTF-8", localesize);
+ DEBUG_printf(("_cupsAppleLocale: Returning \"%s\".", locale));
+
return (locale);
}
#endif /* __APPLE__ */
@@ -669,6 +692,15 @@ cupsLangGet(const char *language) /* I - Language or locale */
*ptr++ = (char)toupper(*language & 255);
*ptr = '\0';
+
+ /*
+ * Map Chinese region codes to legacy country codes.
+ */
+
+ if (!strcmp(language, "zh") && !strcmp(country, "HANS"))
+ strlcpy(country, "CN", sizeof(country));
+ if (!strcmp(language, "zh") && !strcmp(country, "HANT"))
+ strlcpy(country, "TW", sizeof(country));
}
if (*language == '.' && !charset[0])
@@ -688,7 +720,7 @@ cupsLangGet(const char *language) /* I - Language or locale */
* Force a POSIX locale for an invalid language name...
*/
- if (strlen(langname) != 2)
+ if (strlen(langname) != 2 && strlen(langname) != 3)
{
strlcpy(langname, "C", sizeof(langname));
country[0] = '\0';
@@ -828,6 +860,9 @@ _cupsLangString(cups_lang_t *lang, /* I - Language */
{
const char *s; /* Localized message */
+
+ DEBUG_printf(("_cupsLangString(lang=%p, message=\"%s\")", (void *)lang, message));
+
/*
* Range check input...
*/
@@ -1126,6 +1161,8 @@ _cupsMessageLookup(cups_array_t *a, /* I - Message array */
*match; /* Matching message */
+ DEBUG_printf(("_cupsMessageLookup(a=%p, m=\"%s\")", (void *)a, m));
+
/*
* Lookup the message string; if it doesn't exist in the catalog,
* then return the message that was passed to us...
@@ -1336,11 +1373,13 @@ appleMessageLoad(const char *locale) /* I - Locale ID */
{
char filename[1024], /* Path to cups.strings file */
applelang[256], /* Apple language ID */
- baselang[3]; /* Base language */
+ baselang[4]; /* Base language */
CFURLRef url; /* URL to cups.strings file */
CFReadStreamRef stream = NULL; /* File stream */
CFPropertyListRef plist = NULL; /* Localization file */
#ifdef DEBUG
+ const char *cups_strings = getenv("CUPS_STRINGS");
+ /* Test strings file */
CFErrorRef error = NULL; /* Error when opening file */
#endif /* DEBUG */
@@ -1351,6 +1390,15 @@ appleMessageLoad(const char *locale) /* I - Locale ID */
* Load the cups.strings file...
*/
+#ifdef DEBUG
+ if (cups_strings)
+ {
+ DEBUG_puts("1appleMessageLoad: Using debug CUPS_STRINGS file.");
+ strlcpy(filename, cups_strings, sizeof(filename));
+ }
+ else
+#endif /* DEBUG */
+
snprintf(filename, sizeof(filename),
CUPS_BUNDLEDIR "/Resources/%s.lproj/cups.strings",
_cupsAppleLanguage(locale, applelang, sizeof(applelang)));
@@ -1363,6 +1411,7 @@ appleMessageLoad(const char *locale) /* I - Locale ID */
* Try with original locale string...
*/
+ DEBUG_printf(("1appleMessageLoad: \"%s\": %s", filename, strerror(errno)));
snprintf(filename, sizeof(filename), CUPS_BUNDLEDIR "/Resources/%s.lproj/cups.strings", locale);
}
@@ -1374,18 +1423,23 @@ appleMessageLoad(const char *locale) /* I - Locale ID */
* Try with just the language code...
*/
+ DEBUG_printf(("1appleMessageLoad: \"%s\": %s", filename, strerror(errno)));
+
strlcpy(baselang, locale, sizeof(baselang));
+ if (baselang[3] == '-' || baselang[3] == '_')
+ baselang[3] = '\0';
+
snprintf(filename, sizeof(filename), CUPS_BUNDLEDIR "/Resources/%s.lproj/cups.strings", baselang);
}
- DEBUG_printf(("1appleMessageLoad: filename=\"%s\"", filename));
-
if (access(filename, 0))
{
/*
* Try alternate lproj directory names...
*/
+ DEBUG_printf(("1appleMessageLoad: \"%s\": %s", filename, strerror(errno)));
+
if (!strncmp(locale, "en", 2))
locale = "English";
else if (!strncmp(locale, "nb", 2))
@@ -1402,7 +1456,7 @@ appleMessageLoad(const char *locale) /* I - Locale ID */
locale = "Japanese";
else if (!strncmp(locale, "es", 2))
locale = "Spanish";
- else if (!strcmp(locale, "zh_HK") || !strncmp(locale, "zh-Hant", 7))
+ else if (!strcmp(locale, "zh_HK") || !strncasecmp(locale, "zh-Hant", 7) || !strncasecmp(locale, "zh_Hant", 7))
{
/*
* <rdar://problem/22130168>
@@ -1423,14 +1477,18 @@ appleMessageLoad(const char *locale) /* I - Locale ID */
*/
strlcpy(baselang, locale, sizeof(baselang));
+ if (baselang[2] == '-' || baselang[2] == '_')
+ baselang[2] = '\0';
+
locale = baselang;
}
snprintf(filename, sizeof(filename),
CUPS_BUNDLEDIR "/Resources/%s.lproj/cups.strings", locale);
- DEBUG_printf(("1appleMessageLoad: alternate filename=\"%s\"", filename));
}
+ DEBUG_printf(("1appleMessageLoad: filename=\"%s\"", filename));
+
url = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault,
(UInt8 *)filename,
(CFIndex)strlen(filename), false);
diff --git a/cups/language.h b/cups/language.h
index 0a3da779..c96cbfe9 100644
--- a/cups/language.h
+++ b/cups/language.h
@@ -32,7 +32,7 @@ extern "C" {
* Types...
*/
-typedef enum cups_encoding_e /**** Language Encodings ****/
+typedef enum cups_encoding_e /**** Language Encodings @exclude all@ ****/
{
CUPS_AUTO_ENCODING = -1, /* Auto-detect the encoding @private@ */
CUPS_US_ASCII, /* US ASCII */
diff --git a/cups/options.c b/cups/options.c
index aa709928..db14bec7 100644
--- a/cups/options.c
+++ b/cups/options.c
@@ -1,7 +1,7 @@
/*
* Option routines for CUPS.
*
- * Copyright 2007-2014 by Apple Inc.
+ * Copyright 2007-2017 by Apple Inc.
* Copyright 1997-2007 by Easy Software Products.
*
* These coded instructions, statements, and computer programs are the
@@ -30,6 +30,31 @@ static int cups_find_option(const char *name, int num_options,
/*
+ * 'cupsAddIntegerOption()' - Add an integer option to an option array.
+ *
+ * New option arrays can be initialized simply by passing 0 for the
+ * "num_options" parameter.
+ *
+ * @since CUPS 2.2.4/macOS 10.13@
+ */
+
+int /* O - Number of options */
+cupsAddIntegerOption(
+ const char *name, /* I - Name of option */
+ int value, /* I - Value of option */
+ int num_options, /* I - Number of options */
+ cups_option_t **options) /* IO - Pointer to options */
+{
+ char strvalue[32]; /* String value */
+
+
+ snprintf(strvalue, sizeof(strvalue), "%d", value);
+
+ return (cupsAddOption(name, strvalue, num_options, options));
+}
+
+
+/*
* 'cupsAddOption()' - Add an option to an option array.
*
* New option arrays can be initialized simply by passing 0 for the
@@ -55,6 +80,11 @@ cupsAddOption(const char *name, /* I - Name of option */
return (num_options);
}
+ if (!_cups_strcasecmp(name, "cupsPrintQuality"))
+ num_options = cupsRemoveOption("print-quality", num_options, options);
+ else if (!_cups_strcasecmp(name, "print-quality"))
+ num_options = cupsRemoveOption("cupsPrintQuality", num_options, options);
+
/*
* Look for an existing option with the same name...
*/
@@ -155,6 +185,38 @@ cupsFreeOptions(
/*
+ * 'cupsGetIntegerOption()' - Get an integer option value.
+ *
+ * INT_MIN is returned when the option does not exist, is not an integer, or
+ * exceeds the range of values for the "int" type.
+ *
+ * @since CUPS 2.2.4/macOS 10.13@
+ */
+
+int /* O - Option value or @code INT_MIN@ */
+cupsGetIntegerOption(
+ const char *name, /* I - Name of option */
+ int num_options, /* I - Number of options */
+ cups_option_t *options) /* I - Options */
+{
+ const char *value = cupsGetOption(name, num_options, options);
+ /* String value of option */
+ char *ptr; /* Pointer into string value */
+ long intvalue; /* Integer value */
+
+
+ if (!value || !*value)
+ return (INT_MIN);
+
+ intvalue = strtol(value, &ptr, 10);
+ if (intvalue < INT_MIN || intvalue > INT_MAX || *ptr)
+ return (INT_MIN);
+
+ return ((int)intvalue);
+}
+
+
+/*
* 'cupsGetOption()' - Get an option value.
*/
diff --git a/cups/ppd-cache.c b/cups/ppd-cache.c
index e7123410..925ab805 100644
--- a/cups/ppd-cache.c
+++ b/cups/ppd-cache.c
@@ -78,6 +78,8 @@ _cupsConvertOptions(
int num_finishings = 0, /* Number of finishing values */
finishings[10]; /* Finishing enum values */
ppd_choice_t *choice; /* Marked choice */
+ int finishings_copies = copies;
+ /* Number of copies for finishings */
/*
@@ -366,13 +368,13 @@ _cupsConvertOptions(
{
ippAddIntegers(request, IPP_TAG_JOB, IPP_TAG_ENUM, "finishings", num_finishings, finishings);
- if (copies > 1 && (keyword = cupsGetOption("job-impressions", num_options, options)) != NULL)
+ if (copies != finishings_copies && (keyword = cupsGetOption("job-impressions", num_options, options)) != NULL)
{
/*
* Send job-pages-per-set attribute to apply finishings correctly...
*/
- ippAddInteger(request, IPP_TAG_JOB, IPP_TAG_INTEGER, "job-pages-per-set", atoi(keyword) / copies);
+ ippAddInteger(request, IPP_TAG_JOB, IPP_TAG_INTEGER, "job-pages-per-set", atoi(keyword) / finishings_copies);
}
}
@@ -2084,11 +2086,16 @@ _ppdCacheGetFinishingValues(
DEBUG_printf(("_ppdCacheGetFinishingValues(pc=%p, num_options=%d, options=%p, max_values=%d, values=%p)", pc, num_options, options, max_values, values));
- if (!pc || !pc->finishings || num_options < 1 || max_values < 1 || !values)
+ if (!pc || max_values < 1 || !values)
{
DEBUG_puts("_ppdCacheGetFinishingValues: Bad arguments, returning 0.");
return (0);
}
+ else if (!pc->finishings)
+ {
+ DEBUG_puts("_ppdCacheGetFinishingValues: No finishings support, returning 0.");
+ return (0);
+ }
/*
* Go through the finishings options and see what is set...
@@ -2114,7 +2121,7 @@ _ppdCacheGetFinishingValues(
if (i == 0)
{
- DEBUG_printf(("_ppdCacheGetFinishingValues: Adding %d.", f->value));
+ DEBUG_printf(("_ppdCacheGetFinishingValues: Adding %d (%s)", f->value, ippEnumString("finishings", f->value)));
values[num_values ++] = f->value;
@@ -2123,6 +2130,17 @@ _ppdCacheGetFinishingValues(
}
}
+ if (num_values == 0)
+ {
+ /*
+ * Always have at least "finishings" = 'none'...
+ */
+
+ DEBUG_puts("_ppdCacheGetFinishingValues: Adding 3 (none).");
+ values[0] = IPP_FINISHINGS_NONE;
+ num_values ++;
+ }
+
DEBUG_printf(("_ppdCacheGetFinishingValues: Returning %d.", num_values));
return (num_values);
@@ -2949,6 +2967,8 @@ _ppdCreateFromIPP(char *buffer, /* I - Filename buffer */
is_pwg = 0; /* Does the printer support PWG Raster? */
pwg_media_t *pwg; /* PWG media size */
int xres, yres; /* Resolution values */
+ int resolutions[1000];
+ /* Array of resolution indices */
cups_lang_t *lang = cupsLangDefault();
/* Localization info */
struct lconv *loc = localeconv();
@@ -3581,8 +3601,8 @@ _ppdCreateFromIPP(char *buffer, /* I - Filename buffer */
* ColorModel...
*/
- if ((attr = ippFindAttribute(response, "pwg-raster-document-type-supported", IPP_TAG_KEYWORD)) == NULL)
- if ((attr = ippFindAttribute(response, "urf-supported", IPP_TAG_KEYWORD)) == NULL)
+ if ((attr = ippFindAttribute(response, "urf-supported", IPP_TAG_KEYWORD)) == NULL)
+ if ((attr = ippFindAttribute(response, "pwg-raster-document-type-supported", IPP_TAG_KEYWORD)) == NULL)
if ((attr = ippFindAttribute(response, "print-color-mode-supported", IPP_TAG_KEYWORD)) == NULL)
attr = ippFindAttribute(response, "output-mode-supported", IPP_TAG_KEYWORD);
@@ -3595,7 +3615,7 @@ _ppdCreateFromIPP(char *buffer, /* I - Filename buffer */
const char *keyword = ippGetString(attr, i, NULL);
/* Keyword for color/bit depth */
- if (!strcmp(keyword, "black_1") || !strcmp(keyword, "bi-level") || !strcmp(keyword, "process-bi-level"))
+ if (!strcasecmp(keyword, "black_1") || !strcmp(keyword, "bi-level") || !strcmp(keyword, "process-bi-level"))
{
if (!default_color)
cupsFilePrintf(fp, "*OpenUI *ColorModel/%s: PickOne\n"
@@ -3606,7 +3626,7 @@ _ppdCreateFromIPP(char *buffer, /* I - Filename buffer */
if (!default_color)
default_color = "FastGray";
}
- else if (!strcmp(keyword, "sgray_8") || !strcmp(keyword, "W8") || !strcmp(keyword, "monochrome") || !strcmp(keyword, "process-monochrome"))
+ else if (!strcasecmp(keyword, "sgray_8") || !strcmp(keyword, "W8") || !strcmp(keyword, "monochrome") || !strcmp(keyword, "process-monochrome"))
{
if (!default_color)
cupsFilePrintf(fp, "*OpenUI *ColorModel/%s: PickOne\n"
@@ -3617,7 +3637,7 @@ _ppdCreateFromIPP(char *buffer, /* I - Filename buffer */
if (!default_color || !strcmp(default_color, "FastGray"))
default_color = "Gray";
}
- else if (!strcmp(keyword, "srgb_8") || !strcmp(keyword, "SRGB24") || !strcmp(keyword, "color"))
+ else if (!strcasecmp(keyword, "srgb_8") || !strcmp(keyword, "SRGB24") || !strcmp(keyword, "color"))
{
if (!default_color)
cupsFilePrintf(fp, "*OpenUI *ColorModel/%s: PickOne\n"
@@ -3627,7 +3647,7 @@ _ppdCreateFromIPP(char *buffer, /* I - Filename buffer */
default_color = "RGB";
}
- else if (!strcmp(keyword, "adobe-rgb_16") || !strcmp(keyword, "ADOBERGB48"))
+ else if (!strcasecmp(keyword, "adobe-rgb_16") || !strcmp(keyword, "ADOBERGB48"))
{
if (!default_color)
cupsFilePrintf(fp, "*OpenUI *ColorModel/%s: PickOne\n"
@@ -3661,7 +3681,36 @@ _ppdCreateFromIPP(char *buffer, /* I - Filename buffer */
"*Duplex DuplexTumble/%s: \"<</Duplex true/Tumble true>>setpagedevice\"\n"
"*CloseUI: *Duplex\n", _cupsLangString(lang, _("2-Sided Printing")), _cupsLangString(lang, _("Off (1-Sided)")), _cupsLangString(lang, _("Long-Edge (Portrait)")), _cupsLangString(lang, _("Short-Edge (Landscape)")));
- if ((attr = ippFindAttribute(response, "pwg-raster-document-sheet-back", IPP_TAG_KEYWORD)) != NULL)
+ if ((attr = ippFindAttribute(response, "urf-supported", IPP_TAG_KEYWORD)) != NULL)
+ {
+ for (i = 0, count = ippGetCount(attr); i < count; i ++)
+ {
+ const char *dm = ippGetString(attr, i, NULL);
+ /* DM value */
+
+ if (!_cups_strcasecmp(dm, "DM1"))
+ {
+ cupsFilePuts(fp, "*cupsBackSide: Normal\n");
+ break;
+ }
+ else if (!_cups_strcasecmp(dm, "DM2"))
+ {
+ cupsFilePuts(fp, "*cupsBackSide: Flipped\n");
+ break;
+ }
+ else if (!_cups_strcasecmp(dm, "DM3"))
+ {
+ cupsFilePuts(fp, "*cupsBackSide: Rotated\n");
+ break;
+ }
+ else if (!_cups_strcasecmp(dm, "DM4"))
+ {
+ cupsFilePuts(fp, "*cupsBackSide: ManualTumble\n");
+ break;
+ }
+ }
+ }
+ else if ((attr = ippFindAttribute(response, "pwg-raster-document-sheet-back", IPP_TAG_KEYWORD)) != NULL)
{
const char *keyword = ippGetString(attr, 0, NULL);
/* Keyword value */
@@ -3675,35 +3724,6 @@ _ppdCreateFromIPP(char *buffer, /* I - Filename buffer */
else
cupsFilePuts(fp, "*cupsBackSide: Rotated\n");
}
- else if ((attr = ippFindAttribute(response, "urf-supported", IPP_TAG_KEYWORD)) != NULL)
- {
- for (i = 0, count = ippGetCount(attr); i < count; i ++)
- {
- const char *dm = ippGetString(attr, i, NULL);
- /* DM value */
-
- if (!_cups_strcasecmp(dm, "DM1"))
- {
- cupsFilePuts(fp, "*cupsBackSide: Normal\n");
- break;
- }
- else if (!_cups_strcasecmp(dm, "DM2"))
- {
- cupsFilePuts(fp, "*cupsBackSide: Flipped\n");
- break;
- }
- else if (!_cups_strcasecmp(dm, "DM3"))
- {
- cupsFilePuts(fp, "*cupsBackSide: Rotated\n");
- break;
- }
- else if (!_cups_strcasecmp(dm, "DM4"))
- {
- cupsFilePuts(fp, "*cupsBackSide: ManualTumble\n");
- break;
- }
- }
- }
}
/*
@@ -3962,42 +3982,14 @@ _ppdCreateFromIPP(char *buffer, /* I - Filename buffer */
quality = ippFindAttribute(response, "print-quality-supported", IPP_TAG_ENUM);
- if ((attr = ippFindAttribute(response, "pwg-raster-document-resolution-supported", IPP_TAG_RESOLUTION)) != NULL)
- {
- count = ippGetCount(attr);
-
- pwg_ppdize_resolution(attr, count / 2, &xres, &yres, ppdname, sizeof(ppdname));
- cupsFilePrintf(fp, "*DefaultResolution: %s\n", ppdname);
-
- cupsFilePrintf(fp, "*OpenUI *cupsPrintQuality/%s: PickOne\n"
- "*OrderDependency: 10 AnySetup *cupsPrintQuality\n"
- "*DefaultcupsPrintQuality: Normal\n", _cupsLangString(lang, _("Print Quality")));
- if (count > 2 || ippContainsInteger(quality, IPP_QUALITY_DRAFT))
- {
- pwg_ppdize_resolution(attr, 0, &xres, &yres, NULL, 0);
- cupsFilePrintf(fp, "*cupsPrintQuality Draft/%s: \"<</HWResolution[%d %d]>>setpagedevice\"\n", _cupsLangString(lang, _("Draft")), xres, yres);
- }
- pwg_ppdize_resolution(attr, count / 2, &xres, &yres, NULL, 0);
- cupsFilePrintf(fp, "*cupsPrintQuality Normal/%s: \"<</HWResolution[%d %d]>>setpagedevice\"\n", _cupsLangString(lang, _("Normal")), xres, yres);
- if (count > 1 || ippContainsInteger(quality, IPP_QUALITY_HIGH))
- {
- if (count > 1)
- pwg_ppdize_resolution(attr, count - 1, &xres, &yres, NULL, 0);
- else
- pwg_ppdize_resolution(attr, 0, &xres, &yres, NULL, 0);
- cupsFilePrintf(fp, "*cupsPrintQuality High/%s: \"<</HWResolution[%d %d]>>setpagedevice\"\n", _cupsLangString(lang, _("High")), xres, yres);
- }
-
- cupsFilePuts(fp, "*CloseUI: *cupsPrintQuality\n");
- }
- else if ((attr = ippFindAttribute(response, "urf-supported", IPP_TAG_KEYWORD)) != NULL)
+ if ((attr = ippFindAttribute(response, "urf-supported", IPP_TAG_KEYWORD)) != NULL)
{
- int lowdpi = 0, hidpi = 0; /* Lower and higher resolution */
+ int lowdpi = 0, hidpi = 0; /* Lower and higher resolution */
for (i = 0, count = ippGetCount(attr); i < count; i ++)
{
const char *rs = ippGetString(attr, i, NULL);
- /* RS value */
+ /* RS value */
if (_cups_strncasecmp(rs, "RS", 2))
continue;
@@ -4027,18 +4019,81 @@ _ppdCreateFromIPP(char *buffer, /* I - Filename buffer */
cupsFilePrintf(fp, "*DefaultResolution: %ddpi\n", lowdpi);
cupsFilePrintf(fp, "*OpenUI *cupsPrintQuality/%s: PickOne\n"
- "*OrderDependency: 10 AnySetup *cupsPrintQuality\n"
- "*DefaultcupsPrintQuality: Normal\n", _cupsLangString(lang, _("Print Quality")));
+ "*OrderDependency: 10 AnySetup *cupsPrintQuality\n"
+ "*DefaultcupsPrintQuality: Normal\n", _cupsLangString(lang, _("Print Quality")));
if ((lowdpi & 1) == 0)
- cupsFilePrintf(fp, "*cupsPrintQuality Draft/%s: \"<</HWResolution[%d %d]>>setpagedevice\"\n", _cupsLangString(lang, _("Draft")), lowdpi, lowdpi / 2);
+ cupsFilePrintf(fp, "*cupsPrintQuality Draft/%s: \"<</HWResolution[%d %d]>>setpagedevice\"\n", _cupsLangString(lang, _("Draft")), lowdpi, lowdpi / 2);
else if (ippContainsInteger(quality, IPP_QUALITY_DRAFT))
- cupsFilePrintf(fp, "*cupsPrintQuality Draft/%s: \"<</HWResolution[%d %d]>>setpagedevice\"\n", _cupsLangString(lang, _("Draft")), lowdpi, lowdpi);
+ cupsFilePrintf(fp, "*cupsPrintQuality Draft/%s: \"<</HWResolution[%d %d]>>setpagedevice\"\n", _cupsLangString(lang, _("Draft")), lowdpi, lowdpi);
cupsFilePrintf(fp, "*cupsPrintQuality Normal/%s: \"<</HWResolution[%d %d]>>setpagedevice\"\n", _cupsLangString(lang, _("Normal")), lowdpi, lowdpi);
if (hidpi > lowdpi || ippContainsInteger(quality, IPP_QUALITY_HIGH))
- cupsFilePrintf(fp, "*cupsPrintQuality High/%s: \"<</HWResolution[%d %d]>>setpagedevice\"\n", _cupsLangString(lang, _("High")), hidpi, hidpi);
+ cupsFilePrintf(fp, "*cupsPrintQuality High/%s: \"<</HWResolution[%d %d]>>setpagedevice\"\n", _cupsLangString(lang, _("High")), hidpi, hidpi);
cupsFilePuts(fp, "*CloseUI: *cupsPrintQuality\n");
}
}
+ else if ((attr = ippFindAttribute(response, "pwg-raster-document-resolution-supported", IPP_TAG_RESOLUTION)) != NULL)
+ {
+ /*
+ * Make a sorted list of resolutions.
+ */
+
+ count = ippGetCount(attr);
+ if (count > (int)(sizeof(resolutions) / sizeof(resolutions[0])))
+ count = (int)(sizeof(resolutions) / sizeof(resolutions[0]));
+
+ for (i = 0; i < count; i ++)
+ resolutions[i] = i;
+
+ for (i = 0; i < (count - 1); i ++)
+ {
+ for (j = i + 1; j < count; j ++)
+ {
+ int ix, iy, /* First X and Y resolution */
+ jx, jy, /* Second X and Y resolution */
+ temp; /* Swap variable */
+ ipp_res_t units; /* Resolution units */
+
+ ix = ippGetResolution(attr, resolutions[i], &iy, &units);
+ jx = ippGetResolution(attr, resolutions[j], &jy, &units);
+
+ if (ix > jx || (ix == jx && iy > jy))
+ {
+ /*
+ * Swap these two resolutions...
+ */
+
+ temp = resolutions[i];
+ resolutions[i] = resolutions[j];
+ resolutions[j] = temp;
+ }
+ }
+ }
+
+ /*
+ * Generate print quality options...
+ */
+
+ pwg_ppdize_resolution(attr, resolutions[count / 2], &xres, &yres, ppdname, sizeof(ppdname));
+ cupsFilePrintf(fp, "*DefaultResolution: %s\n", ppdname);
+
+ cupsFilePrintf(fp, "*OpenUI *cupsPrintQuality/%s: PickOne\n"
+ "*OrderDependency: 10 AnySetup *cupsPrintQuality\n"
+ "*DefaultcupsPrintQuality: Normal\n", _cupsLangString(lang, _("Print Quality")));
+ if (count > 2 || ippContainsInteger(quality, IPP_QUALITY_DRAFT))
+ {
+ pwg_ppdize_resolution(attr, resolutions[0], &xres, &yres, NULL, 0);
+ cupsFilePrintf(fp, "*cupsPrintQuality Draft/%s: \"<</HWResolution[%d %d]>>setpagedevice\"\n", _cupsLangString(lang, _("Draft")), xres, yres);
+ }
+ pwg_ppdize_resolution(attr, resolutions[count / 2], &xres, &yres, NULL, 0);
+ cupsFilePrintf(fp, "*cupsPrintQuality Normal/%s: \"<</HWResolution[%d %d]>>setpagedevice\"\n", _cupsLangString(lang, _("Normal")), xres, yres);
+ if (count > 1 || ippContainsInteger(quality, IPP_QUALITY_HIGH))
+ {
+ pwg_ppdize_resolution(attr, resolutions[count - 1], &xres, &yres, NULL, 0);
+ cupsFilePrintf(fp, "*cupsPrintQuality High/%s: \"<</HWResolution[%d %d]>>setpagedevice\"\n", _cupsLangString(lang, _("High")), xres, yres);
+ }
+
+ cupsFilePuts(fp, "*CloseUI: *cupsPrintQuality\n");
+ }
else if (is_apple || is_pwg)
goto bad_ppd;
else
diff --git a/cups/ppd-mark.c b/cups/ppd-mark.c
index 9fdaf0bd..464c09a9 100644
--- a/cups/ppd-mark.c
+++ b/cups/ppd-mark.c
@@ -1,7 +1,7 @@
/*
* Option marking routines for CUPS.
*
- * Copyright 2007-2015 by Apple Inc.
+ * Copyright 2007-2017 by Apple Inc.
* Copyright 1997-2007 by Easy Software Products, all rights reserved.
*
* These coded instructions, statements, and computer programs are the
@@ -253,6 +253,7 @@ cupsMarkOptions(
*/
for (i = num_options, optptr = options; i > 0; i --, optptr ++)
+ {
if (!_cups_strcasecmp(optptr->name, "media") ||
!_cups_strcasecmp(optptr->name, "output-bin") ||
!_cups_strcasecmp(optptr->name, "output-mode") ||
@@ -341,6 +342,19 @@ cupsMarkOptions(
ppd_mark_option(ppd, "MirrorPrint", optptr->value);
else
ppd_mark_option(ppd, optptr->name, optptr->value);
+ }
+
+ if (print_quality)
+ {
+ int pq = atoi(print_quality); /* print-quaity value */
+
+ if (pq == IPP_QUALITY_DRAFT)
+ ppd_mark_option(ppd, "cupsPrintQuality", "Draft");
+ else if (pq == IPP_QUALITY_HIGH)
+ ppd_mark_option(ppd, "cupsPrintQuality", "High");
+ else
+ ppd_mark_option(ppd, "cupsPrintQuality", "Normal");
+ }
ppd_debug_marked(ppd, "After...");
diff --git a/cups/pwg-media.c b/cups/pwg-media.c
index 73356fd7..62455ea6 100644
--- a/cups/pwg-media.c
+++ b/cups/pwg-media.c
@@ -189,6 +189,7 @@ static pwg_media_t const cups_pwg_media[] =
_PWG_MEDIA_MM("jis_b1_728x1030mm", "jis-b1", "B1", 728, 1030),
_PWG_MEDIA_MM("jis_b0_1030x1456mm", "jis-b0", "B0", 1030, 1456),
_PWG_MEDIA_MM("jis_exec_216x330mm", NULL, "216x330mm", 216, 330),
+ _PWG_MEDIA_MM("jpn_kaku1_270x382mm", NULL, "EnvKaku1", 270, 382),
_PWG_MEDIA_MM("jpn_kaku2_240x332mm", NULL, "EnvKaku2", 240, 332),
_PWG_MEDIA_MM("jpn_kaku3_216x277mm", NULL, "EnvKaku3", 216, 277),
_PWG_MEDIA_MM("jpn_kaku4_197x267mm", NULL, "EnvKaku4", 197, 267),
diff --git a/cups/pwg.h b/cups/pwg.h
index 2269dbe4..42040509 100644
--- a/cups/pwg.h
+++ b/cups/pwg.h
@@ -1,7 +1,7 @@
/*
* PWG media API definitions for CUPS.
*
- * Copyright 2009-2013 by Apple Inc.
+ * Copyright 2009-2017 by Apple Inc.
*
* These coded instructions, statements, and computer programs are the
* property of Apple Inc. and are protected by Federal copyright
@@ -39,7 +39,7 @@ extern "C" {
* Types and structures...
*/
-typedef struct pwg_map_s /**** Map element - PPD to/from PWG */
+typedef struct pwg_map_s /**** Map element - PPD to/from PWG @exclude all@ */
{
char *pwg, /* PWG media keyword */
*ppd; /* PPD option keyword */
@@ -54,7 +54,7 @@ typedef struct pwg_media_s /**** Common media size data ****/
length; /* Length in 2540ths */
} pwg_media_t;
-typedef struct pwg_size_s /**** Size element - PPD to/from PWG */
+typedef struct pwg_size_s /**** Size element - PPD to/from PWG @exclude all@ */
{
pwg_map_t map; /* Map element */
int width, /* Width in 2540ths */
diff --git a/cups/request.c b/cups/request.c
index 39cbe6cc..efbc06eb 100644
--- a/cups/request.c
+++ b/cups/request.c
@@ -1,7 +1,7 @@
/*
* IPP utilities for CUPS.
*
- * Copyright 2007-2014 by Apple Inc.
+ * Copyright 2007-2017 by Apple Inc.
* Copyright 1997-2007 by Easy Software Products.
*
* These coded instructions, statements, and computer programs are the
@@ -131,13 +131,12 @@ cupsDoIORequest(http_t *http, /* I - Connection to server or @code CUPS_HTTP
* Get the default connection as needed...
*/
- if (!http)
- if ((http = _cupsConnect()) == NULL)
- {
- ippDelete(request);
+ if (!http && (http = _cupsConnect()) == NULL)
+ {
+ ippDelete(request);
- return (NULL);
- }
+ return (NULL);
+ }
/*
* See if we have a file to send...
@@ -151,9 +150,7 @@ cupsDoIORequest(http_t *http, /* I - Connection to server or @code CUPS_HTTP
* Can't get file information!
*/
- _cupsSetError(errno == EBADF ? IPP_STATUS_ERROR_NOT_FOUND : IPP_STATUS_ERROR_NOT_AUTHORIZED,
- NULL, 0);
-
+ _cupsSetError(errno == EBADF ? IPP_STATUS_ERROR_NOT_FOUND : IPP_STATUS_ERROR_NOT_AUTHORIZED, NULL, 0);
ippDelete(request);
return (NULL);
@@ -169,9 +166,8 @@ cupsDoIORequest(http_t *http, /* I - Connection to server or @code CUPS_HTTP
* Can't send a directory...
*/
- ippDelete(request);
-
_cupsSetError(IPP_STATUS_ERROR_NOT_POSSIBLE, strerror(EISDIR), 0);
+ ippDelete(request);
return (NULL);
}
@@ -186,8 +182,7 @@ cupsDoIORequest(http_t *http, /* I - Connection to server or @code CUPS_HTTP
else
length = ippLength(request);
- DEBUG_printf(("2cupsDoIORequest: Request length=%ld, total length=%ld",
- (long)ippLength(request), (long)length));
+ DEBUG_printf(("2cupsDoIORequest: Request length=%ld, total length=%ld", (long)ippLength(request), (long)length));
/*
* Clear any "Local" authentication data since it is probably stale...
@@ -596,6 +591,7 @@ cupsSendRequest(http_t *http, /* I - Connection to server or @code CUPS_HTTP
int got_status; /* Did we get the status? */
ipp_state_t state; /* State of IPP processing */
http_status_t expect; /* Expect: header to use */
+ char date[256]; /* Date: header value */
DEBUG_printf(("cupsSendRequest(http=%p, request=%p(%s), resource=\"%s\", length=" CUPS_LLFMT ")", (void *)http, (void *)request, request ? ippOpString(request->request.op.operation_id) : "?", resource, CUPS_LLCAST length));
@@ -615,9 +611,8 @@ cupsSendRequest(http_t *http, /* I - Connection to server or @code CUPS_HTTP
* Get the default connection as needed...
*/
- if (!http)
- if ((http = _cupsConnect()) == NULL)
- return (HTTP_STATUS_SERVICE_UNAVAILABLE);
+ if (!http && (http = _cupsConnect()) == NULL)
+ return (HTTP_STATUS_SERVICE_UNAVAILABLE);
/*
* If the prior request was not flushed out, do so now...
@@ -685,6 +680,7 @@ cupsSendRequest(http_t *http, /* I - Connection to server or @code CUPS_HTTP
httpClearFields(http);
httpSetExpect(http, expect);
httpSetField(http, HTTP_FIELD_CONTENT_TYPE, "application/ipp");
+ httpSetField(http, HTTP_FIELD_DATE, httpGetDateString2(time(NULL), date, (int)sizeof(date)));
httpSetLength(http, length);
#ifdef HAVE_GSSAPI
@@ -996,7 +992,11 @@ _cupsConnect(void)
*/
if (strcmp(cg->http->hostname, cg->server) ||
+#ifdef AF_LOCAL
+ (httpAddrFamily(cg->http->hostaddr) != AF_LOCAL && cg->ipp_port != httpAddrPort(cg->http->hostaddr)) ||
+#else
cg->ipp_port != httpAddrPort(cg->http->hostaddr) ||
+#endif /* AF_LOCAL */
(cg->http->encryption != cg->encryption &&
cg->http->encryption == HTTP_ENCRYPTION_NEVER))
{
diff --git a/cups/snmp.c b/cups/snmp.c
index fffa2182..7958b93e 100644
--- a/cups/snmp.c
+++ b/cups/snmp.c
@@ -739,6 +739,10 @@ asn1_debug(const char *prefix, /* I - Prefix string */
_cups_globals_t *cg = _cupsGlobals(); /* Global data */
+#ifdef __clang_analyzer__ /* Suppress bogus clang error */
+ memset(string, 0, sizeof(string));
+#endif /* __clang_analyzer__ */
+
if (cg->snmp_debug <= 0)
return;
diff --git a/cups/string.c b/cups/string.c
index 39a787f0..0d4ed0f5 100644
--- a/cups/string.c
+++ b/cups/string.c
@@ -695,10 +695,11 @@ _cups_strlcat(char *dst, /* O - Destination string */
*/
dstlen = strlen(dst);
- size -= dstlen + 1;
- if (!size)
- return (dstlen); /* No room, return immediately... */
+ if (size < (dstlen + 1))
+ return (dstlen); /* No room, return immediately... */
+
+ size -= dstlen + 1;
/*
* Figure out how much room is needed...
diff --git a/cups/testcups.c b/cups/testcups.c
index aa587661..f4931c50 100644
--- a/cups/testcups.c
+++ b/cups/testcups.c
@@ -1,7 +1,7 @@
/*
* CUPS API test program for CUPS.
*
- * Copyright 2007-2014 by Apple Inc.
+ * Copyright 2007-2017 by Apple Inc.
* Copyright 2007 by Easy Software Products.
*
* These coded instructions, statements, and computer programs are the
@@ -47,7 +47,9 @@ main(int argc, /* I - Number of command-line arguments */
cups_dest_t *dests, /* Destinations */
*dest, /* Current destination */
*named_dest; /* Current named destination */
- const char *ppdfile; /* PPD file */
+ const char *dest_name, /* Destination name */
+ *dval, /* Destination value */
+ *ppdfile; /* PPD file */
ppd_file_t *ppd; /* PPD file data */
int num_jobs; /* Number of jobs for queue */
cups_job_t *jobs; /* Jobs for queue */
@@ -360,11 +362,19 @@ main(int argc, /* I - Number of command-line arguments */
* cupsGetDest(printer)
*/
- printf("cupsGetDest(\"%s\"): ", dests[num_dests / 2].name);
+ for (i = 0, dest_name = NULL; i < num_dests; i ++)
+ {
+ if ((dval = cupsGetOption("printer-is-temporary", dests[i].num_options, dest[i].options)) != NULL && !strcmp(dval, "false"))
+ {
+ dest_name = dests[i].name;
+ break;
+ }
+ }
+
+ printf("cupsGetDest(\"%s\"): ", dest_name ? dest_name : "(null)");
fflush(stdout);
- if ((dest = cupsGetDest(dests[num_dests / 2].name, NULL, num_dests,
- dests)) == NULL)
+ if ((dest = cupsGetDest(dest_name, NULL, num_dests, dests)) == NULL)
{
puts("FAIL");
return (1);
@@ -380,8 +390,7 @@ main(int argc, /* I - Number of command-line arguments */
dest->instance ? dest->instance : "(null)");
fflush(stdout);
- if ((named_dest = cupsGetNamedDest(NULL, dest->name,
- dest->instance)) == NULL ||
+ if ((named_dest = cupsGetNamedDest(NULL, dest->name, dest->instance)) == NULL ||
!dests_equal(dest, named_dest))
{
if (named_dest)
@@ -408,7 +417,7 @@ main(int argc, /* I - Number of command-line arguments */
fputs("cupsPrintFile: ", stdout);
fflush(stdout);
- if (cupsPrintFile(dest->name, "../data/testprint", "Test Page",
+ if (cupsPrintFile(dest->name, "../test/testfile.pdf", "Test Page",
dest->num_options, dest->options) <= 0)
{
printf("FAIL (%s)\n", cupsLastErrorString());
@@ -421,7 +430,7 @@ main(int argc, /* I - Number of command-line arguments */
* cupsGetPPD(printer)
*/
- fputs("cupsGetPPD(): ", stdout);
+ fputs("cupsGetPPD: ", stdout);
fflush(stdout);
if ((ppdfile = cupsGetPPD(dest->name)) == NULL)
@@ -436,7 +445,7 @@ main(int argc, /* I - Number of command-line arguments */
* ppdOpenFile()
*/
- fputs("ppdOpenFile(): ", stdout);
+ fputs("ppdOpenFile: ", stdout);
fflush(stdout);
if ((ppd = ppdOpenFile(ppdfile)) == NULL)
@@ -550,33 +559,39 @@ show_diffs(cups_dest_t *a, /* I - First destination */
{
int i; /* Looping var */
cups_option_t *aoption; /* Current option */
+ cups_option_t *boption; /* Current option */
const char *bval; /* Option value */
if (!a || !b)
return;
- puts(" Item cupsGetDest cupsGetNamedDest");
- puts(" -------------------- -------------------- --------------------");
+ puts(" Item cupsGetDest cupsGetNamedDest");
+ puts(" -------------------- ------------------------ ------------------------");
if (_cups_strcasecmp(a->name, b->name))
- printf(" name %-20.20s %-20.20s\n", a->name, b->name);
+ printf(" name %-24.24s %-24.24s\n", a->name, b->name);
if ((a->instance && !b->instance) ||
(!a->instance && b->instance) ||
(a->instance && _cups_strcasecmp(a->instance, b->instance)))
- printf(" instance %-20.20s %-20.20s\n",
+ printf(" instance %-24.24s %-24.24s\n",
a->instance ? a->instance : "(null)",
b->instance ? b->instance : "(null)");
if (a->num_options != b->num_options)
- printf(" num_options %-20d %-20d\n", a->num_options,
+ printf(" num_options %-24d %-24d\n", a->num_options,
b->num_options);
for (i = a->num_options, aoption = a->options; i > 0; i --, aoption ++)
if ((bval = cupsGetOption(aoption->name, b->num_options,
b->options)) == NULL ||
strcmp(aoption->value, bval))
- printf(" %-20.20s %-20.20s %-20.20s\n", aoption->name,
+ printf(" %-20.20s %-24.24s %-24.24s\n", aoption->name,
aoption->value, bval ? bval : "(null)");
+
+ for (i = b->num_options, boption = b->options; i > 0; i --, boption ++)
+ if (!cupsGetOption(boption->name, a->num_options, a->options))
+ printf(" %-20.20s %-24.24s %-24.24s\n", boption->name,
+ boption->value, "(null)");
}
diff --git a/cups/testdest.c b/cups/testdest.c
index 945e3e11..c5c20528 100644
--- a/cups/testdest.c
+++ b/cups/testdest.c
@@ -1,7 +1,7 @@
/*
* CUPS destination API test program for CUPS.
*
- * Copyright 2012-2016 by Apple Inc.
+ * Copyright 2012-2017 by Apple Inc.
*
* These coded instructions, statements, and computer programs are the
* property of Apple Inc. and are protected by Federal copyright
@@ -105,6 +105,14 @@ main(int argc, /* I - Number of command-line arguments */
}
else if (!strncmp(argv[1], "ipp://", 6) || !strncmp(argv[1], "ipps://", 7))
dest = cupsGetDestWithURI(NULL, argv[1]);
+ else if (!strcmp(argv[1], "default"))
+ {
+ dest = cupsGetNamedDest(CUPS_HTTP_DEFAULT, NULL, NULL);
+ if (dest && dest->instance)
+ printf("default is \"%s/%s\".\n", dest->name, dest->instance);
+ else
+ printf("default is \"%s\".\n", dest->name);
+ }
else
dest = cupsGetNamedDest(CUPS_HTTP_DEFAULT, argv[1], NULL);
@@ -218,9 +226,9 @@ enum_cb(void *user_data, /* I - User data (unused) */
(void)flags;
if (dest->instance)
- printf("%s/%s:\n", dest->name, dest->instance);
+ printf("%s%s/%s:\n", (flags & CUPS_DEST_FLAGS_REMOVED) ? "REMOVE " : "", dest->name, dest->instance);
else
- printf("%s:\n", dest->name);
+ printf("%s%s:\n", (flags & CUPS_DEST_FLAGS_REMOVED) ? "REMOVE " : "", dest->name);
for (i = 0; i < dest->num_options; i ++)
printf(" %s=\"%s\"\n", dest->options[i].name, dest->options[i].value);
@@ -463,10 +471,37 @@ show_default(http_t *http, /* I - Connection to destination */
cups_dinfo_t *dinfo, /* I - Destination information */
const char *option) /* I - Option */
{
- (void)http;
- (void)dest;
- (void)dinfo;
- (void)option;
+ if (!strcmp(option, "media"))
+ {
+ /*
+ * Show default media option...
+ */
+
+ cups_size_t size; /* Media size information */
+
+ if (cupsGetDestMediaDefault(http, dest, dinfo, CUPS_MEDIA_FLAGS_DEFAULT, &size))
+ printf("%s (%.2fx%.2fmm, margins=[%.2f %.2f %.2f %.2f])\n", size.media, size.width * 0.01, size.length * 0.01, size.left * 0.01, size.bottom * 0.01, size.right * 0.01, size.top * 0.01);
+ else
+ puts("FAILED");
+ }
+ else
+ {
+ /*
+ * Show default other option...
+ */
+
+ ipp_attribute_t *defattr; /* Default attribute */
+
+ if ((defattr = cupsFindDestDefault(http, dest, dinfo, option)) != NULL)
+ {
+ char value[1024]; /* Value of default attribute */
+
+ ippAttributeString(defattr, value, sizeof(value));
+ puts(value);
+ }
+ else
+ puts("FAILED");
+ }
}
@@ -594,7 +629,8 @@ show_supported(http_t *http, /* I - Connection to destination */
}
else if (!value)
{
- puts(option);
+ printf("%s (%s - %s)\n", option, cupsLocalizeDestOption(http, dest, dinfo, option), cupsCheckDestSupported(http, dest, dinfo, option, NULL) ? "supported" : "not-supported");
+
if ((attr = cupsFindDestSupported(http, dest, dinfo, option)) != NULL)
{
count = ippGetCount(attr);
@@ -608,7 +644,13 @@ show_supported(http_t *http, /* I - Connection to destination */
case IPP_TAG_ENUM :
for (i = 0; i < count; i ++)
- printf(" %s\n", ippEnumString(option, ippGetInteger(attr, i)));
+ {
+ int val = ippGetInteger(attr, i);
+ char valstr[256];
+
+ snprintf(valstr, sizeof(valstr), "%d", val);
+ printf(" %s (%s)\n", ippEnumString(option, ippGetInteger(attr, i)), cupsLocalizeDestValue(http, dest, dinfo, option, valstr));
+ }
break;
case IPP_TAG_RANGE :
@@ -634,11 +676,15 @@ show_supported(http_t *http, /* I - Connection to destination */
}
break;
+ case IPP_TAG_KEYWORD :
+ for (i = 0; i < count; i ++)
+ printf(" %s (%s)\n", ippGetString(attr, i, NULL), cupsLocalizeDestValue(http, dest, dinfo, option, ippGetString(attr, i, NULL)));
+ break;
+
case IPP_TAG_TEXTLANG :
case IPP_TAG_NAMELANG :
case IPP_TAG_TEXT :
case IPP_TAG_NAME :
- case IPP_TAG_KEYWORD :
case IPP_TAG_URI :
case IPP_TAG_URISCHEME :
case IPP_TAG_CHARSET :
diff --git a/cups/testgetdests.c b/cups/testgetdests.c
new file mode 100644
index 00000000..459998f9
--- /dev/null
+++ b/cups/testgetdests.c
@@ -0,0 +1,51 @@
+/*
+ * CUPS cupsGetDests API test program for CUPS.
+ *
+ * Copyright 2017 by Apple Inc.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Apple Inc. and are protected by Federal copyright
+ * law. Distribution and use rights are outlined in the file "LICENSE.txt"
+ * which should have been included with this file. If this file is
+ * missing or damaged, see the license at "http://www.cups.org/".
+ *
+ * This file is subject to the Apple OS-Developed Software exception.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include <stdio.h>
+#include "cups.h"
+#include <sys/time.h>
+
+
+/*
+ * 'main()' - Loop calling cupsGetDests.
+ */
+
+int /* O - Exit status */
+main(void)
+{
+ int num_dests; /* Number of destinations */
+ cups_dest_t *dests; /* Destinations */
+ struct timeval start, end; /* Start and stop time */
+ double secs; /* Total seconds to run cupsGetDests */
+
+
+ for (;;)
+ {
+ gettimeofday(&start, NULL);
+ num_dests = cupsGetDests(&dests);
+ gettimeofday(&end, NULL);
+ secs = end.tv_sec - start.tv_sec + 0.000001 * (end.tv_usec - start.tv_usec);
+
+ printf("Found %d printers in %.3f seconds...\n", num_dests, secs);
+
+ cupsFreeDests(num_dests, dests);
+ sleep(1);
+ }
+
+ return (0);
+}
diff --git a/cups/testipp.c b/cups/testipp.c
index 017ee9d6..ea8f9d78 100644
--- a/cups/testipp.c
+++ b/cups/testipp.c
@@ -1,7 +1,7 @@
/*
* IPP test program for CUPS.
*
- * Copyright 2007-2014 by Apple Inc.
+ * Copyright 2007-2017 by Apple Inc.
* Copyright 1997-2005 by Easy Software Products.
*
* These coded instructions, statements, and computer programs are the
@@ -810,88 +810,9 @@ void
print_attributes(ipp_t *ipp, /* I - IPP request */
int indent) /* I - Indentation */
{
- int i; /* Looping var */
ipp_tag_t group; /* Current group */
ipp_attribute_t *attr; /* Current attribute */
- _ipp_value_t *val; /* Current value */
- static const char * const tags[] = /* Value/group tag strings */
- {
- "reserved-00",
- "operation-attributes-tag",
- "job-attributes-tag",
- "end-of-attributes-tag",
- "printer-attributes-tag",
- "unsupported-attributes-tag",
- "subscription-attributes-tag",
- "event-attributes-tag",
- "reserved-08",
- "reserved-09",
- "reserved-0A",
- "reserved-0B",
- "reserved-0C",
- "reserved-0D",
- "reserved-0E",
- "reserved-0F",
- "unsupported",
- "default",
- "unknown",
- "no-value",
- "reserved-14",
- "not-settable",
- "delete-attr",
- "admin-define",
- "reserved-18",
- "reserved-19",
- "reserved-1A",
- "reserved-1B",
- "reserved-1C",
- "reserved-1D",
- "reserved-1E",
- "reserved-1F",
- "reserved-20",
- "integer",
- "boolean",
- "enum",
- "reserved-24",
- "reserved-25",
- "reserved-26",
- "reserved-27",
- "reserved-28",
- "reserved-29",
- "reserved-2a",
- "reserved-2b",
- "reserved-2c",
- "reserved-2d",
- "reserved-2e",
- "reserved-2f",
- "octetString",
- "dateTime",
- "resolution",
- "rangeOfInteger",
- "begCollection",
- "textWithLanguage",
- "nameWithLanguage",
- "endCollection",
- "reserved-38",
- "reserved-39",
- "reserved-3a",
- "reserved-3b",
- "reserved-3c",
- "reserved-3d",
- "reserved-3e",
- "reserved-3f",
- "reserved-40",
- "textWithoutLanguage",
- "nameWithoutLanguage",
- "reserved-43",
- "keyword",
- "uri",
- "uriScheme",
- "charset",
- "naturalLanguage",
- "mimeMediaType",
- "memberName"
- };
+ char buffer[2048]; /* Value string */
for (group = IPP_TAG_ZERO, attr = ipp->attrs; attr; attr = attr->next)
@@ -907,83 +828,12 @@ print_attributes(ipp_t *ipp, /* I - IPP request */
{
group = attr->group_tag;
- printf("\n%*s%s:\n\n", indent - 4, "", tags[group]);
+ printf("\n%*s%s:\n\n", indent - 4, "", ippTagString(group));
}
- printf("%*s%s (", indent, "", attr->name ? attr->name : "(null)");
- if (attr->num_values > 1)
- printf("1setOf ");
- printf("%s):", tags[attr->value_tag]);
+ ippAttributeString(attr, buffer, sizeof(buffer));
- switch (attr->value_tag)
- {
- case IPP_TAG_ENUM :
- case IPP_TAG_INTEGER :
- for (i = 0, val = attr->values; i < attr->num_values; i ++, val ++)
- printf(" %d", val->integer);
- putchar('\n');
- break;
-
- case IPP_TAG_BOOLEAN :
- for (i = 0, val = attr->values; i < attr->num_values; i ++, val ++)
- printf(" %s", val->boolean ? "true" : "false");
- putchar('\n');
- break;
-
- case IPP_TAG_RANGE :
- for (i = 0, val = attr->values; i < attr->num_values; i ++, val ++)
- printf(" %d-%d", val->range.lower, val->range.upper);
- putchar('\n');
- break;
-
- case IPP_TAG_DATE :
- {
- char vstring[256]; /* Formatted time */
-
- for (i = 0, val = attr->values; i < attr->num_values; i ++, val ++)
- printf(" (%s)", _cupsStrDate(vstring, sizeof(vstring), ippDateToTime(val->date)));
- }
- putchar('\n');
- break;
-
- case IPP_TAG_RESOLUTION :
- for (i = 0, val = attr->values; i < attr->num_values; i ++, val ++)
- printf(" %dx%d%s", val->resolution.xres, val->resolution.yres,
- val->resolution.units == IPP_RES_PER_INCH ? "dpi" : "dpcm");
- putchar('\n');
- break;
-
- case IPP_TAG_STRING :
- case IPP_TAG_TEXTLANG :
- case IPP_TAG_NAMELANG :
- 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 :
- for (i = 0, val = attr->values; i < attr->num_values; i ++, val ++)
- printf(" \"%s\"", val->string.text);
- putchar('\n');
- break;
-
- case IPP_TAG_BEGIN_COLLECTION :
- putchar('\n');
-
- for (i = 0, val = attr->values; i < attr->num_values; i ++, val ++)
- {
- if (i)
- putchar('\n');
- print_attributes(val->collection, indent + 4);
- }
- break;
-
- default :
- printf("UNKNOWN (%d values)\n", attr->num_values);
- break;
- }
+ printf("%*s%s (%s%s): %s\n", indent, "", attr->name ? attr->name : "(null)", attr->num_values > 1 ? "1setOf " : "", ippTagString(attr->value_tag), buffer);
}
}
diff --git a/cups/testlang.c b/cups/testlang.c
index 6aa49ab4..3f140d9b 100644
--- a/cups/testlang.c
+++ b/cups/testlang.c
@@ -1,7 +1,7 @@
/*
* Localization test program for CUPS.
*
- * Copyright 2007-2015 by Apple Inc.
+ * Copyright 2007-2017 by Apple Inc.
* Copyright 1997-2006 by Easy Software Products.
*
* These coded instructions, statements, and computer programs are the
@@ -19,6 +19,16 @@
#include "cups-private.h"
#include "ppd-private.h"
+#ifdef __APPLE__
+# include <CoreFoundation/CoreFoundation.h>
+#endif /* __APPLE__ */
+
+
+/*
+ * Local functions...
+ */
+
+static int test_string(cups_lang_t *language, const char *msgid);
/*
@@ -71,8 +81,9 @@ main(int argc, /* I - Number of command-line arguments */
printf("Language = \"%s\"\n", language->language);
printf("Encoding = \"%s\"\n", _cupsEncodingName(language->encoding));
- printf("No = \"%s\"\n", _cupsLangString(language, "No"));
- printf("Yes = \"%s\"\n", _cupsLangString(language, "Yes"));
+
+ errors += test_string(language, "No");
+ errors += test_string(language, "Yes");
if (language != language2)
{
@@ -138,9 +149,141 @@ main(int argc, /* I - Number of command-line arguments */
}
}
+ printf("media-empty: %s\n", ppdLocalizeIPPReason(ppd, "media-empty", NULL, buffer, sizeof(buffer)));
+
ppdClose(ppd);
}
}
+#ifdef __APPLE__
+ else
+ {
+ /*
+ * Test all possible language IDs for compatibility with _cupsAppleLocale...
+ */
+
+ CFIndex j, /* Looping var */
+ num_locales; /* Number of locales */
+ CFArrayRef locales; /* Locales */
+ CFStringRef locale_id, /* Current locale ID */
+ language_id; /* Current language ID */
+ char locale_str[256], /* Locale ID C string */
+ language_str[256], /* Language ID C string */
+ *bufptr; /* Pointer to ".UTF-8" in POSIX locale */
+ size_t buflen; /* Length of POSIX locale */
+# if TEST_COUNTRY_CODES
+ CFIndex k, /* Looping var */
+ num_country_codes; /* Number of country codes */
+ CFArrayRef country_codes; /* Country codes */
+ CFStringRef country_code, /* Current country code */
+ temp_id; /* Temporary language ID */
+ char country_str[256]; /* Country code C string */
+# endif /* TEST_COUNTRY_CODES */
+
+ locales = CFLocaleCopyAvailableLocaleIdentifiers();
+ num_locales = CFArrayGetCount(locales);
+
+# if TEST_COUNTRY_CODES
+ country_codes = CFLocaleCopyISOCountryCodes();
+ num_country_codes = CFArrayGetCount(country_codes);
+# endif /* TEST_COUNTRY_CODES */
+
+ printf("%d locales are available:\n", (int)num_locales);
+
+ for (j = 0; j < num_locales; j ++)
+ {
+ locale_id = CFArrayGetValueAtIndex(locales, j);
+ language_id = CFLocaleCreateCanonicalLanguageIdentifierFromString(kCFAllocatorDefault, locale_id);
+
+ if (!locale_id || !CFStringGetCString(locale_id, locale_str, (CFIndex)sizeof(locale_str), kCFStringEncodingASCII))
+ {
+ printf("%d: FAIL (unable to get locale ID string)\n", (int)j + 1);
+ errors ++;
+ continue;
+ }
+
+ if (!language_id || !CFStringGetCString(language_id, language_str, (CFIndex)sizeof(language_str), kCFStringEncodingASCII))
+ {
+ printf("%d %s: FAIL (unable to get language ID string)\n", (int)j + 1, locale_str);
+ errors ++;
+ continue;
+ }
+
+ if (!_cupsAppleLocale(language_id, buffer, sizeof(buffer)))
+ {
+ printf("%d %s(%s): FAIL (unable to convert language ID string to POSIX locale)\n", (int)j + 1, locale_str, language_str);
+ errors ++;
+ continue;
+ }
+
+ if ((bufptr = strstr(buffer, ".UTF-8")) != NULL)
+ buflen = (size_t)(bufptr - buffer);
+ else
+ buflen = strlen(buffer);
+
+ if ((language = cupsLangGet(buffer)) == NULL)
+ {
+ printf("%d %s(%s): FAIL (unable to load POSIX locale \"%s\")\n", (int)j + 1, locale_str, language_str, buffer);
+ errors ++;
+ continue;
+ }
+
+ if (strncasecmp(language->language, buffer, buflen))
+ {
+ printf("%d %s(%s): FAIL (unable to load POSIX locale \"%s\", got \"%s\")\n", (int)j + 1, locale_str, language_str, buffer, language->language);
+ errors ++;
+ continue;
+ }
+
+ printf("%d %s(%s): PASS (POSIX locale is \"%s\")\n", (int)j + 1, locale_str, language_str, buffer);
+ }
+
+ CFRelease(locales);
+
+# if TEST_COUNTRY_CODES
+ CFRelease(country_codes);
+# endif /* TEST_COUNTRY_CODES */
+ }
+#endif /* __APPLE__ */
+
+ if (errors == 0)
+ puts("ALL TESTS PASSED");
return (errors > 0);
}
+
+
+/*
+ * 'test_string()' - Test the localization of a string.
+ */
+
+static int /* O - 1 on failure, 0 on success */
+test_string(cups_lang_t *language, /* I - Language */
+ const char *msgid) /* I - Message */
+{
+ const char *msgstr; /* Localized string */
+
+
+ /*
+ * Get the localized string and then see if we got what we expected.
+ *
+ * For the POSIX locale, the string pointers should be the same.
+ * For any other locale, the string pointers should be different.
+ */
+
+ msgstr = _cupsLangString(language, msgid);
+ if (strcmp(language->language, "C") && msgid == msgstr)
+ {
+ printf("%-8s = \"%s\" (FAIL - no message catalog loaded)\n", msgid, msgstr);
+ return (1);
+ }
+ else if (!strcmp(language->language, "C") && msgid != msgstr)
+ {
+ printf("%-8s = \"%s\" (FAIL - POSIX locale is localized)\n", msgid, msgstr);
+ return (1);
+ }
+
+ printf("%-8s = \"%s\" (PASS)\n", msgid, msgstr);
+
+ return (0);
+}
+
diff --git a/cups/thread-private.h b/cups/thread-private.h
index ca4ef4cb..79d24386 100644
--- a/cups/thread-private.h
+++ b/cups/thread-private.h
@@ -1,7 +1,7 @@
/*
* Private threading definitions for CUPS.
*
- * Copyright 2009-2016 by Apple Inc.
+ * Copyright 2009-2017 by Apple Inc.
*
* These coded instructions, statements, and computer programs are the
* property of Apple Inc. and are protected by Federal copyright
@@ -99,6 +99,7 @@ extern void _cupsRWLockWrite(_cups_rwlock_t *rwlock);
extern void _cupsRWUnlock(_cups_rwlock_t *rwlock);
extern void _cupsThreadCancel(_cups_thread_t thread);
extern _cups_thread_t _cupsThreadCreate(_cups_thread_func_t func, void *arg);
+extern void _cupsThreadDetach(_cups_thread_t thread);
extern void *_cupsThreadWait(_cups_thread_t thread);
# ifdef __cplusplus
diff --git a/cups/thread.c b/cups/thread.c
index 77b44426..65257aa1 100644
--- a/cups/thread.c
+++ b/cups/thread.c
@@ -1,7 +1,7 @@
/*
* Threading primitives for CUPS.
*
- * Copyright 2009-2016 by Apple Inc.
+ * Copyright 2009-2017 by Apple Inc.
*
* These coded instructions, statements, and computer programs are the
* property of Apple Inc. and are protected by Federal copyright
@@ -173,6 +173,17 @@ _cupsThreadCreate(
/*
+ * '_cupsThreadDetach()' - Tell the OS that the thread is running independently.
+ */
+
+void
+_cupsThreadDetach(_cups_thread_t thread)/* I - Thread ID */
+{
+ pthread_detach(thread);
+}
+
+
+/*
* '_cupsThreadWait()' - Wait for a thread to exit.
*/
@@ -344,6 +355,18 @@ _cupsThreadCreate(
/*
+ * '_cupsThreadDetach()' - Tell the OS that the thread is running independently.
+ */
+
+void
+_cupsThreadDetach(_cups_thread_t thread)/* I - Thread ID */
+{
+ // TODO: Implement me
+ (void)thread;
+}
+
+
+/*
* '_cupsThreadWait()' - Wait for a thread to exit.
*/
diff --git a/cups/tls-darwin.c b/cups/tls-darwin.c
index b6e88b01..92430aca 100644
--- a/cups/tls-darwin.c
+++ b/cups/tls-darwin.c
@@ -1,7 +1,7 @@
/*
* TLS support code for CUPS on macOS.
*
- * Copyright 2007-2016 by Apple Inc.
+ * Copyright 2007-2017 by Apple Inc.
* Copyright 1997-2007 by Easy Software Products, all rights reserved.
*
* These coded instructions, statements, and computer programs are the
@@ -21,7 +21,7 @@
#include <spawn.h>
-extern char **environ;
+extern char **environ; /* @private@ */
/*
@@ -1141,7 +1141,8 @@ _httpTLSRead(http_t *http, /* I - HTTP connection */
void
_httpTLSSetOptions(int options) /* I - Options */
{
- tls_options = options;
+ if (!(options & _HTTP_TLS_SET_DEFAULT) || tls_options < 0)
+ tls_options = options;
}
@@ -1227,6 +1228,12 @@ _httpTLSStart(http_t *http) /* I - HTTP connection */
error = SSLSetProtocolVersionMin(http->tls, minProtocol);
DEBUG_printf(("4_httpTLSStart: SSLSetProtocolVersionMin(%d), error=%d", minProtocol, (int)error));
+
+ if (!error && (tls_options & _HTTP_TLS_ONLY_TLS10))
+ {
+ error = SSLSetProtocolVersionMax(http->tls, kTLSProtocol1);
+ DEBUG_printf(("4_httpTLSStart: SSLSetProtocolVersionMax(kTLSProtocol1), error=%d", (int)error));
+ }
}
# if HAVE_SSLSETENABLEDCIPHERS
@@ -1324,7 +1331,6 @@ _httpTLSStart(http_t *http) /* I - HTTP connection */
case TLS_DHE_RSA_WITH_AES_256_CBC_SHA :
case TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA :
case TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA :
-// case TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA :
case TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA :
case TLS_DH_DSS_WITH_AES_128_CBC_SHA256 :
case TLS_DH_RSA_WITH_AES_128_CBC_SHA256 :
@@ -1337,6 +1343,14 @@ _httpTLSStart(http_t *http) /* I - HTTP connection */
case TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA :
case TLS_DHE_PSK_WITH_AES_128_CBC_SHA :
case TLS_DHE_PSK_WITH_AES_256_CBC_SHA :
+ case TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 :
+ case TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 :
+ if (tls_options & _HTTP_TLS_DENY_CBC)
+ {
+ DEBUG_printf(("4_httpTLSStart: Excluding CBC cipher suite %d", supported[i]));
+ break;
+ }
+
// case TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 :
// case TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 :
case TLS_DH_RSA_WITH_AES_128_GCM_SHA256 :
@@ -1347,15 +1361,31 @@ _httpTLSStart(http_t *http) /* I - HTTP connection */
case TLS_DH_DSS_WITH_AES_256_GCM_SHA384 :
case TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 :
case TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 :
- case TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 :
- case TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 :
if (tls_options & _HTTP_TLS_ALLOW_DH)
enabled[num_enabled ++] = supported[i];
else
DEBUG_printf(("4_httpTLSStart: Excluding DH/DHE cipher suite %d", supported[i]));
break;
- /* Anything else we'll assume is secure */
+ case TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA :
+ case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 :
+ case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 :
+ case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 :
+ case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 :
+ case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 :
+ case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 :
+ case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 :
+ case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 :
+ case TLS_RSA_WITH_3DES_EDE_CBC_SHA :
+ case TLS_RSA_WITH_AES_128_CBC_SHA :
+ case TLS_RSA_WITH_AES_256_CBC_SHA :
+ if (tls_options & _HTTP_TLS_DENY_CBC)
+ {
+ DEBUG_printf(("4_httpTLSStart: Excluding CBC cipher suite %d", supported[i]));
+ break;
+ }
+
+ /* Anything else we'll assume is "secure" */
default :
enabled[num_enabled ++] = supported[i];
break;
diff --git a/cups/tls-gnutls.c b/cups/tls-gnutls.c
index 7193d794..2dcb7fe3 100644
--- a/cups/tls-gnutls.c
+++ b/cups/tls-gnutls.c
@@ -1,7 +1,7 @@
/*
* TLS support code for CUPS using GNU TLS.
*
- * Copyright 2007-2016 by Apple Inc.
+ * Copyright 2007-2017 by Apple Inc.
* Copyright 1997-2007 by Easy Software Products, all rights reserved.
*
* These coded instructions, statements, and computer programs are the
@@ -397,7 +397,7 @@ httpCredentialsAreValidForName(
for (i = 0; i < count; i ++)
{
rserial_size = sizeof(rserial);
- if (!gnutls_x509_crl_get_crt_serial(tls_crl, i, rserial, &rserial_size, NULL) && cserial_size == rserial_size && !memcmp(cserial, rserial, rserial_size))
+ if (!gnutls_x509_crl_get_crt_serial(tls_crl, (unsigned)i, rserial, &rserial_size, NULL) && cserial_size == rserial_size && !memcmp(cserial, rserial, rserial_size))
{
result = 0;
break;
@@ -1226,7 +1226,8 @@ _httpTLSSetCredentials(http_t *http) /* I - Connection to server */
void
_httpTLSSetOptions(int options) /* I - Options */
{
- tls_options = options;
+ if (!(options & _HTTP_TLS_SET_DEFAULT) || tls_options < 0)
+ tls_options = options;
}
@@ -1242,7 +1243,7 @@ _httpTLSStart(http_t *http) /* I - Connection to server */
int status; /* Status of handshake */
gnutls_certificate_credentials_t *credentials;
/* TLS credentials */
- char priority_string[1024];
+ char priority_string[2048];
/* Priority string */
@@ -1508,15 +1509,21 @@ _httpTLSStart(http_t *http) /* I - Connection to server */
if (tls_options & _HTTP_TLS_DENY_TLS10)
strlcat(priority_string, ":+VERS-TLS-ALL:-VERS-TLS1.0:-VERS-SSL3.0", sizeof(priority_string));
else if (tls_options & _HTTP_TLS_ALLOW_SSL3)
- strlcat(priority_string, ":+VERS-TLS-ALL", sizeof(priority_string));
+ strlcat(priority_string, ":+VERS-TLS-ALL:+VERS-SSL3.0", sizeof(priority_string));
+ else if (tls_options & _HTTP_TLS_ONLY_TLS10)
+ strlcat(priority_string, ":-VERS-TLS-ALL:-VERS-SSL3.0:+VERS-TLS1.0", sizeof(priority_string));
else
strlcat(priority_string, ":+VERS-TLS-ALL:-VERS-SSL3.0", sizeof(priority_string));
- if (!(tls_options & _HTTP_TLS_ALLOW_RC4))
- strlcat(priority_string, ":-ARCFOUR-128", sizeof(priority_string));
+ if (tls_options & _HTTP_TLS_ALLOW_RC4)
+ strlcat(priority_string, ":+ARCFOUR-128", sizeof(priority_string));
+ else
+ strlcat(priority_string, ":!ARCFOUR-128", sizeof(priority_string));
+
+ strlcat(priority_string, ":!ANON-DH", sizeof(priority_string));
- if (!(tls_options & _HTTP_TLS_ALLOW_DH))
- strlcat(priority_string, ":!ANON-DH", sizeof(priority_string));
+ if (tls_options & _HTTP_TLS_DENY_CBC)
+ strlcat(priority_string, ":!AES-128-CBC:!AES-256-CBC:!CAMELLIA-128-CBC:!CAMELLIA-256-CBC:!3DES-CBC", sizeof(priority_string));
#ifdef HAVE_GNUTLS_PRIORITY_SET_DIRECT
gnutls_priority_set_direct(http->tls, priority_string, NULL);
diff --git a/cups/tls-sspi.c b/cups/tls-sspi.c
index 46f6e790..6eaec4c8 100644
--- a/cups/tls-sspi.c
+++ b/cups/tls-sspi.c
@@ -2,7 +2,7 @@
* TLS support for CUPS on Windows using the Security Support Provider
* Interface (SSPI).
*
- * Copyright 2010-2015 by Apple Inc.
+ * Copyright 2010-2017 by Apple Inc.
*
* These coded instructions, statements, and computer programs are the
* property of Apple Inc. and are protected by Federal copyright
@@ -913,7 +913,8 @@ _httpTLSRead(http_t *http, /* I - HTTP connection */
void
_httpTLSSetOptions(int options) /* I - Options */
{
- tls_options = options;
+ if (!(options & _HTTP_TLS_SET_DEFAULT) || tls_options < 0)
+ tls_options = options;
}
@@ -1795,7 +1796,7 @@ http_sspi_find_credentials(
}
#endif /* SP_PROT_TLS1_2_SERVER */
- /* TODO: Support _HTTP_TLS_ALLOW_RC4 and _HTTP_TLS_ALLOW_DH options; right now we'll rely on Windows registry to enable/disable RC4/DH... */
+ /* TODO: Support _HTTP_TLS_ALLOW_RC4, _HTTP_TLS_ALLOW_DH, and _HTTP_TLS_DENY_CBC options; right now we'll rely on Windows registry to enable/disable RC4/DH/CBC... */
/*
* Create an SSPI credential.
diff --git a/cups/tlscheck.c b/cups/tlscheck.c
index 32cbcca1..997e7aaf 100644
--- a/cups/tlscheck.c
+++ b/cups/tlscheck.c
@@ -1,7 +1,7 @@
/*
* TLS check program for CUPS.
*
- * Copyright 2007-2015 by Apple Inc.
+ * Copyright 2007-2017 by Apple Inc.
* Copyright 1997-2006 by Easy Software Products.
*
* These coded instructions, statements, and computer programs are the
@@ -82,10 +82,18 @@ main(int argc, /* I - Number of command-line arguments */
{
tls_options |= _HTTP_TLS_ALLOW_DH;
}
+ else if (!strcmp(argv[i], "--no-cbc"))
+ {
+ tls_options |= _HTTP_TLS_DENY_CBC;
+ }
else if (!strcmp(argv[i], "--no-tls10"))
{
tls_options |= _HTTP_TLS_DENY_TLS10;
}
+ else if (!strcmp(argv[i], "--tls10"))
+ {
+ tls_options |= _HTTP_TLS_ONLY_TLS10;
+ }
else if (!strcmp(argv[i], "--rc4"))
{
tls_options |= _HTTP_TLS_ALLOW_RC4;
@@ -729,8 +737,10 @@ usage(void)
puts("");
puts("Options:");
puts(" --dh Allow DH/DHE key exchange");
+ puts(" --no-cbc Disable CBC cipher suites");
puts(" --no-tls10 Disable TLS/1.0");
puts(" --rc4 Allow RC4 encryption");
+ puts(" --tls10 Only use TLS/1.0");
puts(" --verbose Be verbose");
puts(" -4 Connect using IPv4 addresses only");
puts(" -6 Connect using IPv6 addresses only");
diff --git a/cups/usersys.c b/cups/usersys.c
index 333d21e0..2a004b54 100644
--- a/cups/usersys.c
+++ b/cups/usersys.c
@@ -1,7 +1,7 @@
/*
* User, system, and password routines for CUPS.
*
- * Copyright 2007-2015 by Apple Inc.
+ * Copyright 2007-2017 by Apple Inc.
* Copyright 1997-2006 by Easy Software Products.
*
* These coded instructions, statements, and computer programs are the
@@ -132,6 +132,8 @@ cupsEncryption(void)
* thread in a program. Multi-threaded programs that override the setting via
* the @link cupsSetPasswordCB@ or @link cupsSetPasswordCB2@ functions need to
* do so in each thread for the same function to be used.
+ *
+ * @exclude all@
*/
const char * /* O - Password */
@@ -145,7 +147,7 @@ cupsGetPassword(const char *prompt) /* I - Prompt string */
/*
- * 'cupsGetPassword2()' - Get a password from the user using the advanced
+ * 'cupsGetPassword2()' - Get a password from the user using the current
* password callback.
*
* Uses the current password callback function. Returns @code NULL@ if the
@@ -153,8 +155,8 @@ cupsGetPassword(const char *prompt) /* I - Prompt string */
*
* Note: The current password callback function is tracked separately for each
* thread in a program. Multi-threaded programs that override the setting via
- * the @link cupsSetPasswordCB@ or @link cupsSetPasswordCB2@ functions need to
- * do so in each thread for the same function to be used.
+ * the @link cupsSetPasswordCB2@ function need to do so in each thread for the
+ * same function to be used.
*
* @since CUPS 1.4/macOS 10.6@
*/
@@ -297,6 +299,8 @@ cupsSetEncryption(http_encryption_t e) /* I - New encryption preference */
* Note: The current password callback is tracked separately for each thread
* in a program. Multi-threaded programs that override the callback need to do
* so in each thread for the same callback to be used.
+ *
+ * @exclude all@
*/
void
@@ -953,7 +957,7 @@ _cupsSetDefaults(void)
cg->validate_certs = cc.validate_certs;
#ifdef HAVE_SSL
- _httpTLSSetOptions(cc.ssl_options);
+ _httpTLSSetOptions(cc.ssl_options | _HTTP_TLS_SET_DEFAULT);
#endif /* HAVE_SSL */
}
@@ -1171,7 +1175,7 @@ cups_init_client_conf(
* everything...)
*/
-#ifdef __APPLE__
+#if defined(__APPLE__) && defined(HAVE_SSL)
char sval[1024]; /* String value */
int bval; /* Boolean value */
@@ -1192,7 +1196,7 @@ cups_init_client_conf(
if (cups_apple_get_boolean(kValidateCertsKey, &bval))
cc->validate_certs = bval;
-#endif /* __APPLE__ */
+#endif /* __APPLE__ && HAVE_SSL */
}
@@ -1363,6 +1367,8 @@ cups_set_ssl_options(
options |= _HTTP_TLS_ALLOW_SSL3;
else if (!_cups_strcasecmp(start, "AllowDH"))
options |= _HTTP_TLS_ALLOW_DH;
+ else if (!_cups_strcasecmp(start, "DenyCBC"))
+ options |= _HTTP_TLS_DENY_CBC;
else if (!_cups_strcasecmp(start, "DenyTLS1.0"))
options |= _HTTP_TLS_DENY_TLS10;
else if (!_cups_strcasecmp(start, "None"))
diff --git a/cups/util.c b/cups/util.c
index 5db2fc6c..2f5ebdf4 100644
--- a/cups/util.c
+++ b/cups/util.c
@@ -1,7 +1,7 @@
/*
* Printing utilities for CUPS.
*
- * Copyright 2007-2015 by Apple Inc.
+ * Copyright 2007-2017 by Apple Inc.
* Copyright 1997-2006 by Easy Software Products.
*
* These coded instructions, statements, and computer programs are the
@@ -28,6 +28,19 @@
/*
+ * Enumeration data and callback...
+ */
+
+typedef struct _cups_createdata_s
+{
+ const char *name; /* Destination name */
+ cups_dest_t *dest; /* Matching destination */
+} _cups_createdata_t;
+
+static int cups_create_cb(_cups_createdata_t *data, unsigned flags, cups_dest_t *dest);
+
+
+/*
* 'cupsCancelJob()' - Cancel a print job on the default server.
*
* Pass @code CUPS_JOBID_ALL@ to cancel all jobs or @code CUPS_JOBID_CURRENT@
@@ -35,6 +48,8 @@
*
* Use the @link cupsLastError@ and @link cupsLastErrorString@ functions to get
* the cause of any failure.
+ *
+ * @exclude all@
*/
int /* O - 1 on success, 0 on failure */
@@ -58,7 +73,7 @@ cupsCancelJob(const char *name, /* I - Name of printer or class */
* Use the @link cupsLastError@ and @link cupsLastErrorString@ functions to get
* the cause of any failure.
*
- * @since CUPS 1.4/macOS 10.6@
+ * @since CUPS 1.4/macOS 10.6@ @exclude all@
*/
ipp_status_t /* O - IPP status */
@@ -146,7 +161,7 @@ cupsCancelJob2(http_t *http, /* I - Connection to server or @code CUPS_HTTP_
* print, use the @link cupsPrintFile2@ or @link cupsPrintFiles2@ function
* instead.
*
- * @since CUPS 1.4/macOS 10.6@
+ * @since CUPS 1.4/macOS 10.6@ @exclude all@
*/
int /* O - Job ID or 0 on error */
@@ -157,12 +172,10 @@ cupsCreateJob(
int num_options, /* I - Number of options */
cups_option_t *options) /* I - Options */
{
- char printer_uri[1024], /* Printer URI */
- resource[1024]; /* Printer resource */
- ipp_t *request, /* Create-Job request */
- *response; /* Create-Job response */
- ipp_attribute_t *attr; /* job-id attribute */
int job_id = 0; /* job-id value */
+ ipp_status_t status; /* Create-Job status */
+ _cups_createdata_t data; /* Enumeration data */
+ cups_dinfo_t *info; /* Destination information */
DEBUG_printf(("cupsCreateJob(http=%p, name=\"%s\", title=\"%s\", num_options=%d, options=%p)", (void *)http, name, title, num_options, (void *)options));
@@ -178,46 +191,47 @@ cupsCreateJob(
}
/*
- * Build a Create-Job request...
+ * Lookup the destination...
*/
- if ((request = ippNewRequest(IPP_OP_CREATE_JOB)) == NULL)
+ data.name = name;
+ data.dest = NULL;
+
+ cupsEnumDests(0, 1000, NULL, 0, 0, (cups_dest_cb_t)cups_create_cb, &data);
+
+ if (!data.dest)
{
- _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(ENOMEM), 0);
+ DEBUG_puts("1cupsCreateJob: Destination not found.");
+ _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(ENOENT), 0);
return (0);
}
- httpAssembleURIf(HTTP_URI_CODING_ALL, printer_uri, sizeof(printer_uri), "ipp",
- NULL, "localhost", ippPort(), "/printers/%s", name);
- snprintf(resource, sizeof(resource), "/printers/%s", name);
-
- ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
- NULL, printer_uri);
- ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
- NULL, cupsUser());
- if (title)
- ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "job-name", NULL,
- title);
- cupsEncodeOptions2(request, num_options, options, IPP_TAG_OPERATION);
- cupsEncodeOptions2(request, num_options, options, IPP_TAG_JOB);
- cupsEncodeOptions2(request, num_options, options, IPP_TAG_SUBSCRIPTION);
-
/*
- * Send the request and get the job-id...
+ * Query dest information and create the job...
*/
- response = cupsDoRequest(http, request, resource);
+ DEBUG_puts("1cupsCreateJob: Querying destination info.");
+ if ((info = cupsCopyDestInfo(http, data.dest)) == NULL)
+ {
+ DEBUG_puts("1cupsCreateJob: Query failed.");
+ cupsFreeDests(1, data.dest);
+ return (0);
+ }
- if ((attr = ippFindAttribute(response, "job-id", IPP_TAG_INTEGER)) != NULL)
- job_id = attr->values[0].integer;
+ status = cupsCreateDestJob(http, data.dest, info, &job_id, title, num_options, options);
+ DEBUG_printf(("1cupsCreateJob: cupsCreateDestJob returned %04x (%s)", status, ippErrorString(status)));
- ippDelete(response);
+ cupsFreeDestInfo(info);
+ cupsFreeDests(1, data.dest);
/*
- * Return it...
+ * Return the job...
*/
- return (job_id);
+ if (status >= IPP_STATUS_REDIRECTION_OTHER_SITE)
+ return (0);
+ else
+ return (job_id);
}
@@ -226,7 +240,7 @@ cupsCreateJob(
*
* The document must have been started using @link cupsStartDocument@.
*
- * @since CUPS 1.4/macOS 10.6@
+ * @since CUPS 1.4/macOS 10.6@ @exclude all@
*/
ipp_status_t /* O - Status of document submission */
@@ -277,7 +291,7 @@ cupsFreeJobs(int num_jobs, /* I - Number of jobs */
* This function is deprecated and no longer returns a list of printer
* classes - use @link cupsGetDests@ instead.
*
- * @deprecated@
+ * @deprecated@ @exclude all@
*/
int /* O - Number of classes */
@@ -299,6 +313,8 @@ cupsGetClasses(char ***classes) /* O - Classes */
* Applications should use the @link cupsGetDests@ and @link cupsGetDest@
* functions to get the user-defined default printer, as this function does
* not support the lpoptions-defined default printer.
+ *
+ * @exclude all@
*/
const char * /* O - Default printer or @code NULL@ */
@@ -322,7 +338,7 @@ cupsGetDefault(void)
* functions to get the user-defined default printer, as this function does
* not support the lpoptions-defined default printer.
*
- * @since CUPS 1.1.21/macOS 10.4@
+ * @since CUPS 1.1.21/macOS 10.4@ @exclude all@
*/
const char * /* O - Default printer or @code NULL@ */
@@ -388,6 +404,8 @@ cupsGetDefault2(http_t *http) /* I - Connection to server or @code CUPS_HTTP_DE
* of state, while @code CUPS_WHICHJOBS_ACTIVE@ returns jobs that are
* pending, processing, or held and @code CUPS_WHICHJOBS_COMPLETED@ returns
* jobs that are stopped, canceled, aborted, or completed.
+ *
+ * @exclude all@
*/
int /* O - Number of jobs */
@@ -683,7 +701,7 @@ cupsGetJobs2(http_t *http, /* I - Connection to server or @code CUPS_HTTP_D
* This function is deprecated and no longer returns a list of printers - use
* @link cupsGetDests@ instead.
*
- * @deprecated@
+ * @deprecated@ @exclude all@
*/
int /* O - Number of printers */
@@ -698,6 +716,8 @@ cupsGetPrinters(char ***printers) /* O - Printers */
/*
* 'cupsPrintFile()' - Print a file to a printer or class on the default server.
+ *
+ * @exclude all@
*/
int /* O - Job ID or 0 on error */
@@ -718,7 +738,7 @@ cupsPrintFile(const char *name, /* I - Destination name */
* 'cupsPrintFile2()' - Print a file to a printer or class on the specified
* server.
*
- * @since CUPS 1.1.21/macOS 10.4@
+ * @since CUPS 1.1.21/macOS 10.4@ @exclude all@
*/
int /* O - Job ID or 0 on error */
@@ -740,6 +760,8 @@ cupsPrintFile2(
/*
* 'cupsPrintFiles()' - Print one or more files to a printer or class on the
* default server.
+ *
+ * @exclude all@
*/
int /* O - Job ID or 0 on error */
@@ -766,7 +788,7 @@ cupsPrintFiles(
* 'cupsPrintFiles2()' - Print one or more files to a printer or class on the
* specified server.
*
- * @since CUPS 1.1.21/macOS 10.4@
+ * @since CUPS 1.1.21/macOS 10.4@ @exclude all@
*/
int /* O - Job ID or 0 on error */
@@ -896,7 +918,7 @@ cupsPrintFiles2(
* @code CUPS_FORMAT_TEXT@ are provided for the "format" argument, although
* any supported MIME type string can be supplied.
*
- * @since CUPS 1.4/macOS 10.6@
+ * @since CUPS 1.4/macOS 10.6@ @exclude all@
*/
http_status_t /* O - HTTP status of request */
@@ -951,3 +973,26 @@ cupsStartDocument(
return (status);
}
+
+
+/*
+ * 'cups_create_cb()' - Find the destination for printing.
+ */
+
+static int /* O - 0 on match */
+cups_create_cb(
+ _cups_createdata_t *data, /* I - Data from cupsCreateJob call */
+ unsigned flags, /* I - Enumeration flags */
+ cups_dest_t *dest) /* I - Destination */
+{
+ DEBUG_printf(("2cups_create_cb(data=%p(%s), flags=%08x, dest=%p(%s))", (void *)data, data->name, flags, (void *)dest, dest->name));
+
+ (void)flags;
+
+ if (dest->instance || strcasecmp(data->name, dest->name))
+ return (1);
+
+ cupsCopyDest(dest, 0, &data->dest);
+
+ return (0);
+}
diff --git a/cups/versioning.h b/cups/versioning.h
index 2e92e6ba..5a000c05 100644
--- a/cups/versioning.h
+++ b/cups/versioning.h
@@ -1,7 +1,7 @@
/*
* API versioning definitions for CUPS.
*
- * Copyright 2007-2016 by Apple Inc.
+ * Copyright 2007-2017 by Apple Inc.
*
* These coded instructions, statements, and computer programs are the
* property of Apple Inc. and are protected by Federal copyright
@@ -17,11 +17,10 @@
/*
* This header defines several constants - _CUPS_DEPRECATED,
- * _CUPS_DEPRECATED_MSG, _CUPS_INTERNAL_MSG, _CUPS_API_1_1, _CUPS_API_1_1_19,
- * _CUPS_API_1_1_20, _CUPS_API_1_1_21, _CUPS_API_1_2, _CUPS_API_1_3,
- * _CUPS_API_1_4, _CUPS_API_1_5, _CUPS_API_1_6, _CUPS_API_1_7, and
- * _CUPS_API_2_0 - which add compiler-specific attributes that flag functions
- * that are deprecated, added in particular releases, or internal to CUPS.
+ * _CUPS_DEPRECATED_MSG, _CUPS_INTERNAL_MSG, _CUPS_API_major_minor, and
+ * _CUPS_API_major_minor_patch - which add compiler-specific attributes that
+ * flag functions that are deprecated, added in particular releases, or internal
+ * to CUPS.
*
* On macOS, the _CUPS_API_* constants are defined based on the values of
* the MAC_OS_X_VERSION_MIN_ALLOWED and MAC_OS_X_VERSION_MAX_ALLOWED constants
@@ -57,6 +56,9 @@
# ifndef AVAILABLE_MAC_OS_X_VERSION_10_12_AND_LATER
# define AVAILABLE_MAC_OS_X_VERSION_10_12_AND_LATER __attribute__((unavailable))
# endif /* !AVAILABLE_MAC_OS_X_VERSION_10_12_AND_LATER */
+# ifndef AVAILABLE_MAC_OS_X_VERSION_10_13_AND_LATER
+# define AVAILABLE_MAC_OS_X_VERSION_10_13_AND_LATER __attribute__((unavailable))
+# endif /* !AVAILABLE_MAC_OS_X_VERSION_10_13_AND_LATER */
# define _CUPS_API_1_1_19 AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER
# define _CUPS_API_1_1_20 AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER
# define _CUPS_API_1_1_21 AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER
@@ -68,6 +70,7 @@
# define _CUPS_API_1_7 AVAILABLE_MAC_OS_X_VERSION_10_9_AND_LATER
# define _CUPS_API_2_0 AVAILABLE_MAC_OS_X_VERSION_10_10_AND_LATER
# define _CUPS_API_2_2 AVAILABLE_MAC_OS_X_VERSION_10_12_AND_LATER
+# define _CUPS_API_2_2_4 AVAILABLE_MAC_OS_X_VERSION_10_13_AND_LATER
# else
# define _CUPS_API_1_1_19
# define _CUPS_API_1_1_20
@@ -80,6 +83,7 @@
# define _CUPS_API_1_7
# define _CUPS_API_2_0
# define _CUPS_API_2_2
+# define _CUPS_API_2_2_4
# endif /* __APPLE__ && !_CUPS_SOURCE */
/*
diff --git a/filter/Makefile b/filter/Makefile
index 7da764d3..02aab14d 100644
--- a/filter/Makefile
+++ b/filter/Makefile
@@ -1,7 +1,7 @@
#
# Filter makefile for CUPS.
#
-# Copyright 2007-2012 by Apple Inc.
+# Copyright 2007-2017 by Apple Inc.
# Copyright 1997-2006 by Easy Software Products.
#
# These coded instructions, statements, and computer programs are the
@@ -29,6 +29,7 @@ LIBTARGETS = \
libcupsimage.a
UNITTARGETS = \
rasterbench \
+ testclient \
testraster
TARGETS = \
$(LIBTARGETS) \
@@ -38,7 +39,7 @@ IMAGEOBJS = error.o interpret.o raster.o
OBJS = $(IMAGEOBJS) \
commandtops.o gziptoany.o common.o pstops.o \
rasterbench.o rastertoepson.o rastertohp.o rastertolabel.o \
- rastertopwg.o testraster.o
+ rastertopwg.o testclient.o testraster.o
#
@@ -216,7 +217,7 @@ apihelp:
commandtops: commandtops.o ../cups/$(LIBCUPS)
echo Linking $@...
- $(CC) $(LDFLAGS) -o $@ commandtops.o $(LIBS)
+ $(LD_CC) $(LDFLAGS) -o $@ commandtops.o $(LIBS)
#
@@ -225,7 +226,7 @@ commandtops: commandtops.o ../cups/$(LIBCUPS)
gziptoany: gziptoany.o ../Makedefs ../cups/$(LIBCUPS)
echo Linking $@...
- $(CC) $(LDFLAGS) -o $@ gziptoany.o $(LIBZ) $(LIBS)
+ $(LD_CC) $(LDFLAGS) -o $@ gziptoany.o $(LIBZ) $(LIBS)
#
@@ -295,7 +296,7 @@ libcupsimage.a: $(IMAGEOBJS)
pstops: pstops.o common.o ../cups/$(LIBCUPS)
echo Linking $@...
- $(CC) $(LDFLAGS) -o $@ pstops.o common.o $(LIBS)
+ $(LD_CC) $(LDFLAGS) -o $@ pstops.o common.o $(LIBS)
#
@@ -304,7 +305,7 @@ pstops: pstops.o common.o ../cups/$(LIBCUPS)
rastertoepson: rastertoepson.o ../cups/$(LIBCUPS) $(LIBCUPSIMAGE)
echo Linking $@...
- $(CC) $(LDFLAGS) -o $@ rastertoepson.o $(LINKCUPSIMAGE) $(IMGLIBS) $(LIBS)
+ $(LD_CC) $(LDFLAGS) -o $@ rastertoepson.o $(LINKCUPSIMAGE) $(IMGLIBS) $(LIBS)
#
@@ -313,7 +314,7 @@ rastertoepson: rastertoepson.o ../cups/$(LIBCUPS) $(LIBCUPSIMAGE)
rastertohp: rastertohp.o ../cups/$(LIBCUPS) $(LIBCUPSIMAGE)
echo Linking $@...
- $(CC) $(LDFLAGS) -o $@ rastertohp.o $(LINKCUPSIMAGE) $(IMGLIBS) $(LIBS)
+ $(LD_CC) $(LDFLAGS) -o $@ rastertohp.o $(LINKCUPSIMAGE) $(IMGLIBS) $(LIBS)
#
@@ -322,7 +323,7 @@ rastertohp: rastertohp.o ../cups/$(LIBCUPS) $(LIBCUPSIMAGE)
rastertolabel: rastertolabel.o ../cups/$(LIBCUPS) $(LIBCUPSIMAGE)
echo Linking $@...
- $(CC) $(LDFLAGS) -o $@ rastertolabel.o $(LINKCUPSIMAGE) $(IMGLIBS) $(LIBS)
+ $(LD_CC) $(LDFLAGS) -o $@ rastertolabel.o $(LINKCUPSIMAGE) $(IMGLIBS) $(LIBS)
#
@@ -331,22 +332,33 @@ rastertolabel: rastertolabel.o ../cups/$(LIBCUPS) $(LIBCUPSIMAGE)
rastertopwg: rastertopwg.o ../cups/$(LIBCUPS) $(LIBCUPSIMAGE)
echo Linking $@...
- $(CC) $(LDFLAGS) -o $@ rastertopwg.o $(LINKCUPSIMAGE) $(IMGLIBS) $(LIBS)
+ $(LD_CC) $(LDFLAGS) -o $@ rastertopwg.o $(LINKCUPSIMAGE) $(IMGLIBS) $(LIBS)
rastertopwg-static: rastertopwg.o ../cups/$(LIBCUPSSTATIC) libcupsimage.a
echo Linking $@...
- $(CC) $(LDFLAGS) -o $@ rastertopwg.o libcupsimage.a \
+ $(LD_CC) $(LDFLAGS) -o $@ rastertopwg.o libcupsimage.a \
../cups/$(LIBCUPSSTATIC) $(IMGLIBS) $(DSOLIBS) $(COMMONLIBS) \
$(SSLLIBS) $(DNSSDLIBS) $(LIBGSSAPI)
#
+# testclient (dependency on static libraries is intentional)
+#
+
+testclient: testclient.o ../cups/$(LIBCUPSSTATIC) libcupsimage.a
+ echo Linking $@...
+ $(LD_CC) $(LDFLAGS) -o $@ testclient.o \
+ libcupsimage.a ../cups/$(LIBCUPSSTATIC) \
+ $(LIBGSSAPI) $(SSLLIBS) $(DNSSDLIBS) $(COMMONLIBS) $(LIBZ)
+
+
+#
# testraster
#
testraster: testraster.o ../cups/$(LIBCUPSSTATIC) libcupsimage.a
echo Linking $@...
- $(CC) $(ARCHFLAGS) $(LDFLAGS) -o $@ testraster.o libcupsimage.a \
+ $(LD_CC) $(ARCHFLAGS) $(LDFLAGS) -o $@ testraster.o libcupsimage.a \
../cups/$(LIBCUPSSTATIC) $(IMGLIBS) $(DSOLIBS) $(COMMONLIBS) \
$(SSLLIBS) $(DNSSDLIBS) $(LIBGSSAPI)
echo Running raster API tests...
@@ -359,7 +371,7 @@ testraster: testraster.o ../cups/$(LIBCUPSSTATIC) libcupsimage.a
rasterbench: rasterbench.o libcupsimage.a
echo Linking $@...
- $(CC) $(LDFLAGS) -o $@ rasterbench.o libcupsimage.a $(LIBS)
+ $(LD_CC) $(LDFLAGS) -o $@ rasterbench.o libcupsimage.a $(LIBS)
#
diff --git a/filter/testclient.c b/filter/testclient.c
new file mode 100644
index 00000000..3a9c032c
--- /dev/null
+++ b/filter/testclient.c
@@ -0,0 +1,960 @@
+/*
+ * Simulated client test program for CUPS.
+ *
+ * Copyright 2017 by Apple Inc.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Apple Inc. and are protected by Federal copyright
+ * law. Distribution and use rights are outlined in the file "LICENSE.txt"
+ * which should have been included with this file. If this file is
+ * missing or damaged, see the license at "http://www.cups.org/".
+ *
+ * This file is subject to the Apple OS-Developed Software exception.
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <cups/cups.h>
+#include <cups/raster.h>
+#include <cups/string-private.h>
+#include <cups/thread-private.h>
+
+
+/*
+ * Local types...
+ */
+
+typedef struct _client_monitor_s
+{
+ const char *uri, /* Printer URI */
+ *hostname, /* Hostname */
+ *user, /* Username */
+ *resource; /* Resource path */
+ int port; /* Port number */
+ http_encryption_t encryption; /* Use encryption? */
+ ipp_pstate_t printer_state; /* Current printer state */
+ char printer_state_reasons[1024];
+ /* Current printer-state-reasons */
+ int job_id; /* Job ID for submitted job */
+ ipp_jstate_t job_state; /* Current job state */
+ char job_state_reasons[1024];
+ /* Current job-state-reasons */
+} _client_monitor_t;
+
+
+/*
+ * Local functions...
+ */
+
+static const char *make_raster_file(ipp_t *response, int grayscale, char *tempname, size_t tempsize, const char **format);
+static void *monitor_printer(_client_monitor_t *monitor);
+static void show_attributes(const char *title, int request, ipp_t *ipp);
+static void show_capabilities(ipp_t *response);
+static void usage(void);
+
+
+/*
+ * 'main()' - Main entry.
+ */
+
+int /* O - Exit status */
+main(int argc, /* I - Number of command-line arguments */
+ char *argv[]) /* I - Command-line arguments */
+{
+ int i; /* Looping var */
+ const char *opt, /* Current option */
+ *uri = NULL, /* Printer URI */
+ *printfile = NULL,
+ /* Print file */
+ *printformat = NULL;
+ /* Print format */
+ int keepfile = 0, /* Keep temp file? */
+ grayscale = 0, /* Force grayscale? */
+ verbosity = 0; /* Verbosity */
+ char tempfile[1024] = "",
+ /* Temporary file (if any) */
+ scheme[32], /* URI scheme */
+ userpass[256], /* Username:password */
+ hostname[256], /* Hostname */
+ resource[256]; /* Resource path */
+ int port; /* Port number */
+ http_encryption_t encryption; /* Encryption mode */
+ _client_monitor_t monitor; /* Monitoring data */
+ http_t *http; /* HTTP connection */
+ ipp_t *request, /* IPP request */
+ *response; /* IPP response */
+ ipp_attribute_t *attr; /* IPP attribute */
+ static const char * const pattrs[] = /* Printer attributes we are interested in */
+ {
+ "job-template",
+ "printer-defaults",
+ "printer-description",
+ "media-col-database",
+ "media-col-ready"
+ };
+
+
+ /*
+ * Parse command-line options...
+ */
+
+ for (i = 1; i < argc; i ++)
+ {
+ if (argv[i][0] == '-')
+ {
+ for (opt = argv[i] + 1; *opt; opt ++)
+ {
+ switch (*opt)
+ {
+ case 'd' : /* -d document-format */
+ if (printformat)
+ {
+ puts("Document format can only be specified once.");
+ usage();
+ return (1);
+ }
+
+ i ++;
+ if (i >= argc)
+ {
+ puts("Expected document format after '-d'.");
+ usage();
+ return (1);
+ }
+
+ printformat = argv[i];
+ break;
+
+ case 'f' : /* -f print-file */
+ if (printfile)
+ {
+ puts("Print file can only be specified once.");
+ usage();
+ return (1);
+ }
+
+ i ++;
+ if (i >= argc)
+ {
+ puts("Expected print file after '-f'.");
+ usage();
+ return (1);
+ }
+
+ printfile = argv[i];
+ break;
+
+ case 'g' :
+ grayscale = 1;
+ break;
+
+ case 'k' :
+ keepfile = 1;
+ break;
+
+ case 'v' :
+ verbosity ++;
+ break;
+
+ default :
+ printf("Unknown option '-%c'.\n", *opt);
+ usage();
+ return (1);
+ }
+ }
+ }
+ else if (uri || (strncmp(argv[i], "ipp://", 6) && strncmp(argv[i], "ipps://", 7)))
+ {
+ printf("Unknown command-line argument '%s'.\n", argv[i]);
+ usage();
+ return (1);
+ }
+ else
+ uri = argv[i];
+ }
+
+ /*
+ * Make sure we have everything we need.
+ */
+
+ if (!uri)
+ {
+ puts("Expected printer URI.");
+ usage();
+ return (1);
+ }
+
+ /*
+ * Connect to the printer...
+ */
+
+ if (httpSeparateURI(HTTP_URI_CODING_ALL, uri, scheme, sizeof(scheme), userpass, sizeof(userpass), hostname, sizeof(hostname), &port, resource, sizeof(resource)) < HTTP_URI_STATUS_OK)
+ {
+ printf("Bad printer URI '%s'.\n", uri);
+ return (1);
+ }
+
+ if (!port)
+ port = IPP_PORT;
+
+ if (!strcmp(scheme, "https") || !strcmp(scheme, "ipps"))
+ encryption = HTTP_ENCRYPTION_ALWAYS;
+ else
+ encryption = HTTP_ENCRYPTION_IF_REQUESTED;
+
+ if ((http = httpConnect2(hostname, port, NULL, AF_UNSPEC, encryption, 1, 0, NULL)) == NULL)
+ {
+ printf("Unable to connect to '%s' on port %d: %s\n", hostname, port, cupsLastErrorString());
+ return (1);
+ }
+
+ /*
+ * Query printer status and capabilities...
+ */
+
+ request = ippNewRequest(IPP_OP_GET_PRINTER_ATTRIBUTES);
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, uri);
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, cupsUser());
+ ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, "requested-attributes", (int)(sizeof(pattrs) / sizeof(pattrs[0])), NULL, pattrs);
+
+ response = cupsDoRequest(http, request, resource);
+
+ if (verbosity)
+ show_capabilities(response);
+
+ /*
+ * Now figure out what we will be printing...
+ */
+
+ if (printfile)
+ {
+ /*
+ * User specified a print file, figure out the format...
+ */
+
+ if ((opt = strrchr(printfile, '.')) != NULL)
+ {
+ /*
+ * Guess the format from the extension...
+ */
+
+ if (!strcmp(opt, ".jpg"))
+ printformat = "image/jpeg";
+ else if (!strcmp(opt, ".pdf"))
+ printformat = "application/pdf";
+ else if (!strcmp(opt, ".ps"))
+ printformat = "application/postscript";
+ else if (!strcmp(opt, ".pwg"))
+ printformat = "image/pwg-raster";
+ else if (!strcmp(opt, ".urf"))
+ printformat = "image/urf";
+ else
+ printformat = "application/octet-stream";
+ }
+ else
+ {
+ /*
+ * Tell the printer to auto-detect...
+ */
+
+ printformat = "application/octet-stream";
+ }
+ }
+ else
+ {
+ /*
+ * No file specified, make something to test with...
+ */
+
+ if ((printfile = make_raster_file(response, grayscale, tempfile, sizeof(tempfile), &printformat)) == NULL)
+ return (1);
+ }
+
+ ippDelete(response);
+
+ /*
+ * Start monitoring the printer in the background...
+ */
+
+ memset(&monitor, 0, sizeof(monitor));
+
+ monitor.uri = uri;
+ monitor.hostname = hostname;
+ monitor.resource = resource;
+ monitor.port = port;
+ monitor.encryption = encryption;
+
+ _cupsThreadCreate((_cups_thread_func_t)monitor_printer, &monitor);
+
+ /*
+ * Create the job and wait for completion...
+ */
+
+ request = ippNewRequest(IPP_OP_CREATE_JOB);
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, uri);
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, cupsUser());
+
+ if ((opt = strrchr(printfile, '/')) != NULL)
+ opt ++;
+ else
+ opt = printfile;
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "job-name", NULL, opt);
+
+ if (verbosity)
+ show_attributes("Create-Job request", 1, request);
+
+ response = cupsDoRequest(http, request, resource);
+
+ if (verbosity)
+ show_attributes("Create-Job response", 0, response);
+
+ if (cupsLastError() >= IPP_STATUS_REDIRECTION_OTHER_SITE)
+ {
+ printf("Unable to create print job: %s\n", cupsLastErrorString());
+
+ monitor.job_state = IPP_JSTATE_ABORTED;
+
+ goto cleanup;
+ }
+
+ if ((attr = ippFindAttribute(response, "job-id", IPP_TAG_INTEGER)) == NULL)
+ {
+ puts("No job-id returned in Create-Job request.");
+
+ monitor.job_state = IPP_JSTATE_ABORTED;
+
+ goto cleanup;
+ }
+
+ monitor.job_id = ippGetInteger(attr, 0);
+
+ printf("CREATED JOB %d, sending %s of type %s\n", monitor.job_id, printfile, printformat);
+
+ ippDelete(response);
+
+ request = ippNewRequest(IPP_OP_SEND_DOCUMENT);
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, uri);
+ ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_INTEGER, "job-id", monitor.job_id);
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, cupsUser());
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_MIMETYPE, "document-format", NULL, printformat);
+ ippAddBoolean(request, IPP_TAG_OPERATION, "last-document", 1);
+
+ if (verbosity)
+ show_attributes("Send-Document request", 1, request);
+
+ response = cupsDoFileRequest(http, request, resource, printfile);
+
+ if (verbosity)
+ show_attributes("Send-Document response", 0, response);
+
+ if (cupsLastError() >= IPP_STATUS_REDIRECTION_OTHER_SITE)
+ {
+ printf("Unable to print file: %s\n", cupsLastErrorString());
+
+ monitor.job_state = IPP_JSTATE_ABORTED;
+
+ goto cleanup;
+ }
+
+ puts("WAITING FOR JOB TO COMPLETE");
+
+ while (monitor.job_state < IPP_JSTATE_CANCELED)
+ sleep(1);
+
+ /*
+ * Cleanup after ourselves...
+ */
+
+ cleanup:
+
+ httpClose(http);
+
+ if (tempfile[0] && !keepfile)
+ unlink(tempfile);
+
+ return (monitor.job_state == IPP_JSTATE_COMPLETED);
+}
+
+
+/*
+ * 'make_raster_file()' - Create a temporary raster file.
+ */
+
+static const char * /* O - Print filename */
+make_raster_file(ipp_t *response, /* I - Printer attributes */
+ int grayscale, /* I - Force grayscale? */
+ char *tempname, /* I - Temporary filename buffer */
+ size_t tempsize, /* I - Size of temp file buffer */
+ const char **format) /* O - Print format */
+{
+ int i, /* Looping var */
+ count; /* Number of values */
+ ipp_attribute_t *attr; /* Printer attribute */
+ const char *type = NULL; /* Raster type (colorspace + bits) */
+ pwg_media_t *media = NULL; /* Media size */
+ int xdpi = 0, /* Horizontal resolution */
+ ydpi = 0; /* Vertical resolution */
+ int fd; /* Temporary file */
+ cups_mode_t mode; /* Raster mode */
+ cups_raster_t *ras; /* Raster stream */
+ cups_page_header2_t header; /* Page header */
+ unsigned char *line, /* Line of raster data */
+ *lineptr; /* Pointer into line */
+ unsigned y, /* Current position on page */
+ xcount, ycount, /* Current count for X and Y */
+ xrep, yrep, /* Repeat count for X and Y */
+ xoff, yoff, /* Offsets for X and Y */
+ yend; /* End Y value */
+ int temprow, /* Row in template */
+ tempcolor; /* Template color */
+ const char *template; /* Pointer into template */
+ const unsigned char *color; /* Current color */
+ static const unsigned char colors[][3] =
+ { /* Colors for test */
+ { 191, 191, 191 },
+ { 127, 127, 127 },
+ { 63, 63, 63 },
+ { 0, 0, 0 },
+ { 255, 0, 0 },
+ { 255, 127, 0 },
+ { 255, 255, 0 },
+ { 127, 255, 0 },
+ { 0, 255, 0 },
+ { 0, 255, 127 },
+ { 0, 255, 255 },
+ { 0, 127, 255 },
+ { 0, 0, 255 },
+ { 127, 0, 255 },
+ { 255, 0, 255 }
+ };
+ static const char * const templates[] =
+ { /* Raster template */
+ " CCC U U PPPP SSS TTTTT EEEEE SSS TTTTT 000 1 222 333 4 55555 66 77777 888 999 ",
+ "C C U U P P S S T E S S T 0 0 11 2 2 3 3 4 4 5 6 7 8 8 9 9 ",
+ "C U U P P S T E S T 0 0 1 2 3 4 4 5 6 7 8 8 9 9 ",
+ "C U U PPPP SSS ----- T EEEE SSS T 0 0 0 1 22 333 44444 555 6666 7 888 9999 ",
+ "C U U P S T E S T 0 0 1 2 3 4 5 6 6 7 8 8 9 ",
+ "C C U U P S S T E S S T 0 0 1 2 3 3 4 5 5 6 6 7 8 8 9 ",
+ " CCC UUU P SSS T EEEEE SSS T 000 111 22222 333 4 555 666 7 888 99 ",
+ " "
+ };
+
+
+ /*
+ * Figure out the output format...
+ */
+
+ if ((attr = ippFindAttribute(response, "document-format-supported", IPP_TAG_MIMETYPE)) == NULL)
+ {
+ puts("No supported document formats, aborting.");
+ return (NULL);
+ }
+
+ if (*format)
+ {
+ if (!ippContainsString(attr, *format))
+ {
+ printf("Printer does not support document-format '%s'.\n", *format);
+ return (NULL);
+ }
+
+ if (!strcmp(*format, "image/urf"))
+ mode = CUPS_RASTER_WRITE_APPLE;
+ else if (!strcmp(*format, "image/pwg-raster"))
+ mode = CUPS_RASTER_WRITE_PWG;
+ else
+ {
+ printf("Unable to generate document-format '%s'.\n", *format);
+ return (NULL);
+ }
+ }
+ else if (ippContainsString(attr, "image/urf"))
+ {
+ /*
+ * Apple Raster format...
+ */
+
+ *format = "image/urf";
+ mode = CUPS_RASTER_WRITE_APPLE;
+ }
+ else if (ippContainsString(attr, "image/pwg-raster"))
+ {
+ /*
+ * PWG Raster format...
+ */
+
+ *format = "image/pwg-raster";
+ mode = CUPS_RASTER_WRITE_PWG;
+ }
+ else
+ {
+ /*
+ * No supported raster format...
+ */
+
+ puts("Printer does not support Apple or PWG raster files, aborting.");
+ return (NULL);
+ }
+
+ /*
+ * Figure out the the media, resolution, and color mode...
+ */
+
+ if ((attr = ippFindAttribute(response, "media-default", IPP_TAG_KEYWORD)) != NULL)
+ {
+ /*
+ * Use default media...
+ */
+
+ media = pwgMediaForPWG(ippGetString(attr, 0, NULL));
+ }
+ else if ((attr = ippFindAttribute(response, "media-ready", IPP_TAG_KEYWORD)) != NULL)
+ {
+ /*
+ * Use ready media...
+ */
+
+ if (ippContainsString(attr, "na_letter_8.5x11in"))
+ media = pwgMediaForPWG("na_letter_8.5x11in");
+ else if (ippContainsString(attr, "iso_a4_210x297mm"))
+ media = pwgMediaForPWG("iso_a4_210x297mm");
+ else
+ media = pwgMediaForPWG(ippGetString(attr, 0, NULL));
+ }
+ else
+ {
+ puts("No default or ready media reported by printer, aborting.");
+ return (NULL);
+ }
+
+ if (mode == CUPS_RASTER_WRITE_APPLE && (attr = ippFindAttribute(response, "urf-supported", IPP_TAG_KEYWORD)) != NULL)
+ {
+ for (i = 0, count = ippGetCount(attr); i < count; i ++)
+ {
+ const char *val = ippGetString(attr, i, NULL);
+
+ if (!strncmp(val, "RS", 2))
+ xdpi = ydpi = atoi(val + 2);
+ else if (!strncmp(val, "W8", 2) && !type)
+ type = "sgray_8";
+ else if (!strncmp(val, "SRGB24", 6) && !grayscale)
+ type = "srgb_8";
+ }
+ }
+ else if (mode == CUPS_RASTER_WRITE_PWG && (attr = ippFindAttribute(response, "pwg-raster-document-resolution-supported", IPP_TAG_RESOLUTION)) != NULL)
+ {
+ for (i = 0, count = ippGetCount(attr); i < count; i ++)
+ {
+ int tempxdpi, tempydpi;
+ ipp_res_t tempunits;
+
+ tempxdpi = ippGetResolution(attr, 0, &tempydpi, &tempunits);
+
+ if (i == 0 || tempxdpi < xdpi || tempydpi < ydpi)
+ {
+ xdpi = tempxdpi;
+ ydpi = tempydpi;
+ }
+ }
+
+ if ((attr = ippFindAttribute(response, "pwg-raster-document-type-supported", IPP_TAG_KEYWORD)) != NULL)
+ {
+ if (!grayscale && ippContainsString(attr, "srgb_8"))
+ type = "srgb_8";
+ else if (ippContainsString(attr, "sgray_8"))
+ type = "sgray_8";
+ }
+ }
+
+ if (xdpi < 72 || ydpi < 72)
+ {
+ puts("No supported raster resolutions, aborting.");
+ return (NULL);
+ }
+
+ if (!type)
+ {
+ puts("No supported color spaces or bit depths, aborting.");
+ return (NULL);
+ }
+
+ /*
+ * Make the raster context and details...
+ */
+
+ if (!cupsRasterInitPWGHeader(&header, media, type, xdpi, ydpi, "one-sided", NULL))
+ {
+ printf("Unable to initialize raster context: %s\n", cupsRasterErrorString());
+ return (NULL);
+ }
+
+ header.cupsInteger[CUPS_RASTER_PWG_TotalPageCount] = 1;
+
+ if (header.cupsWidth > (4 * header.HWResolution[0]))
+ {
+ xoff = header.HWResolution[0] / 2;
+ yoff = header.HWResolution[1] / 2;
+ }
+ else
+ {
+ xoff = 0;
+ yoff = 0;
+ }
+
+ xrep = (header.cupsWidth - 2 * xoff) / 140;
+ yrep = xrep * header.HWResolution[1] / header.HWResolution[0];
+ yend = header.cupsHeight - yoff;
+
+ /*
+ * Prepare the raster file...
+ */
+
+ if ((line = malloc(header.cupsBytesPerLine)) == NULL)
+ {
+ printf("Unable to allocate %u bytes for raster output: %s\n", header.cupsBytesPerLine, strerror(errno));
+ return (NULL);
+ }
+
+ if ((fd = cupsTempFd(tempname, (int)tempsize)) < 0)
+ {
+ printf("Unable to create temporary print file: %s\n", strerror(errno));
+ return (NULL);
+ }
+
+ if ((ras = cupsRasterOpen(fd, mode)) == NULL)
+ {
+ printf("Unable to open raster stream: %s\n", cupsRasterErrorString());
+ close(fd);
+ return (NULL);
+ }
+
+ /*
+ * Write a single page consisting of the template dots repeated over the page.
+ */
+
+ cupsRasterWriteHeader2(ras, &header);
+
+ memset(line, 0xff, header.cupsBytesPerLine);
+
+ for (y = 0; y < yoff; y ++)
+ cupsRasterWritePixels(ras, line, header.cupsBytesPerLine);
+
+ for (temprow = 0, tempcolor = 0; y < yend;)
+ {
+ template = templates[temprow];
+ color = colors[tempcolor];
+
+ temprow ++;
+ if (temprow >= (int)(sizeof(templates) / sizeof(templates[0])))
+ {
+ temprow = 0;
+ tempcolor ++;
+ if (tempcolor >= (int)(sizeof(colors) / sizeof(colors[0])))
+ tempcolor = 0;
+ else if (tempcolor > 3 && header.cupsColorSpace == CUPS_CSPACE_SW)
+ tempcolor = 0;
+ }
+
+ memset(line, 0xff, header.cupsBytesPerLine);
+
+ if (header.cupsColorSpace == CUPS_CSPACE_SW)
+ {
+ /*
+ * Do grayscale output...
+ */
+
+ for (lineptr = line + xoff; *template; template ++)
+ {
+ if (*template != ' ')
+ {
+ for (xcount = xrep; xcount > 0; xcount --)
+ *lineptr++ = *color;
+ }
+ else
+ {
+ lineptr += xrep;
+ }
+ }
+ }
+ else
+ {
+ /*
+ * Do color output...
+ */
+
+ for (lineptr = line + 3 * xoff; *template; template ++)
+ {
+ if (*template != ' ')
+ {
+ for (xcount = xrep; xcount > 0; xcount --, lineptr += 3)
+ memcpy(lineptr, color, 3);
+ }
+ else
+ {
+ lineptr += 3 * xrep;
+ }
+ }
+ }
+
+ for (ycount = yrep; ycount > 0 && y < yend; ycount --, y ++)
+ cupsRasterWritePixels(ras, line, header.cupsBytesPerLine);
+ }
+
+ memset(line, 0xff, header.cupsBytesPerLine);
+
+ for (y = 0; y < header.cupsHeight; y ++)
+ cupsRasterWritePixels(ras, line, header.cupsBytesPerLine);
+
+ cupsRasterClose(ras);
+
+ close(fd);
+
+ printf("PRINT FILE: %s\n", tempname);
+
+ return (tempname);
+}
+
+
+/*
+ * 'monitor_printer()' - Monitor the job and printer states.
+ */
+
+static void * /* O - Thread exit code */
+monitor_printer(
+ _client_monitor_t *monitor) /* I - Monitoring data */
+{
+ http_t *http; /* Connection to printer */
+ ipp_t *request, /* IPP request */
+ *response; /* IPP response */
+ ipp_attribute_t *attr; /* Attribute in response */
+ ipp_pstate_t printer_state; /* Printer state */
+ char printer_state_reasons[1024];
+ /* Printer state reasons */
+ ipp_jstate_t job_state; /* Job state */
+ char job_state_reasons[1024];/* Printer state reasons */
+ static const char * const jattrs[] = /* Job attributes we want */
+ {
+ "job-state",
+ "job-state-reasons"
+ };
+ static const char * const pattrs[] = /* Printer attributes we want */
+ {
+ "printer-state",
+ "printer-state-reasons"
+ };
+
+
+ /*
+ * Open a connection to the printer...
+ */
+
+ http = httpConnect2(monitor->hostname, monitor->port, NULL, AF_UNSPEC, monitor->encryption, 1, 0, NULL);
+
+ /*
+ * Loop until the job is canceled, aborted, or completed.
+ */
+
+ printer_state = (ipp_pstate_t)0;
+ printer_state_reasons[0] = '\0';
+
+ job_state = (ipp_jstate_t)0;
+ job_state_reasons[0] = '\0';
+
+ while (monitor->job_state < IPP_JSTATE_CANCELED)
+ {
+ /*
+ * Reconnect to the printer as needed...
+ */
+
+ if (httpGetFd(http) < 0)
+ httpReconnect2(http, 30000, NULL);
+
+ if (httpGetFd(http) >= 0)
+ {
+ /*
+ * Connected, so check on the printer state...
+ */
+
+ request = ippNewRequest(IPP_OP_GET_PRINTER_ATTRIBUTES);
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, monitor->uri);
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, cupsUser());
+ ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, "requested-attributes", (int)(sizeof(pattrs) / sizeof(pattrs[0])), NULL, pattrs);
+
+ response = cupsDoRequest(http, request, monitor->resource);
+
+ if ((attr = ippFindAttribute(response, "printer-state", IPP_TAG_ENUM)) != NULL)
+ printer_state = (ipp_pstate_t)ippGetInteger(attr, 0);
+
+ if ((attr = ippFindAttribute(response, "printer-state-reasons", IPP_TAG_KEYWORD)) != NULL)
+ ippAttributeString(attr, printer_state_reasons, sizeof(printer_state_reasons));
+
+ if (printer_state != monitor->printer_state || strcmp(printer_state_reasons, monitor->printer_state_reasons))
+ {
+ printf("PRINTER: %s (%s)\n", ippEnumString("printer-state", printer_state), printer_state_reasons);
+
+ monitor->printer_state = printer_state;
+ strlcpy(monitor->printer_state_reasons, printer_state_reasons, sizeof(monitor->printer_state_reasons));
+ }
+
+ ippDelete(response);
+
+ if (monitor->job_id > 0)
+ {
+ /*
+ * Check the status of the job itself...
+ */
+
+ request = ippNewRequest(IPP_OP_GET_JOB_ATTRIBUTES);
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, monitor->uri);
+ ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_INTEGER, "job-id", monitor->job_id);
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, cupsUser());
+ ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, "requested-attributes", (int)(sizeof(jattrs) / sizeof(jattrs[0])), NULL, jattrs);
+
+ response = cupsDoRequest(http, request, monitor->resource);
+
+ if ((attr = ippFindAttribute(response, "job-state", IPP_TAG_ENUM)) != NULL)
+ job_state = (ipp_jstate_t)ippGetInteger(attr, 0);
+
+ if ((attr = ippFindAttribute(response, "job-state-reasons", IPP_TAG_KEYWORD)) != NULL)
+ ippAttributeString(attr, job_state_reasons, sizeof(job_state_reasons));
+
+ if (job_state != monitor->job_state || strcmp(job_state_reasons, monitor->job_state_reasons))
+ {
+ printf("JOB %d: %s (%s)\n", monitor->job_id, ippEnumString("job-state", job_state), job_state_reasons);
+
+ monitor->job_state = job_state;
+ strlcpy(monitor->job_state_reasons, job_state_reasons, sizeof(monitor->job_state_reasons));
+ }
+
+ ippDelete(response);
+ }
+ }
+
+ if (monitor->job_state < IPP_JSTATE_CANCELED)
+ {
+ /*
+ * Sleep for 5 seconds...
+ */
+
+ sleep(5);
+ }
+ }
+
+ /*
+ * Cleanup and return...
+ */
+
+ httpClose(http);
+
+ return (NULL);
+}
+
+
+/*
+ * 'show_attributes()' - Show attributes in a request or response.
+ */
+
+static void
+show_attributes(const char *title, /* I - Title */
+ int request, /* I - 1 for request, 0 for response */
+ ipp_t *ipp) /* I - IPP request/response */
+{
+ int minor, major = ippGetVersion(ipp, &minor);
+ /* IPP version number */
+ ipp_tag_t group = IPP_TAG_ZERO;
+ /* Current group tag */
+ ipp_attribute_t *attr; /* Current attribute */
+ const char *name; /* Attribute name */
+ char buffer[1024]; /* Value */
+
+
+ printf("%s:\n", title);
+ printf(" version=%d.%d\n", major, minor);
+ printf(" request-id=%d\n", ippGetRequestId(ipp));
+ if (!request)
+ printf(" status-code=%s\n", ippErrorString(ippGetStatusCode(ipp)));
+
+ for (attr = ippFirstAttribute(ipp); attr; attr = ippNextAttribute(ipp))
+ {
+ if (group != ippGetGroupTag(attr))
+ {
+ group = ippGetGroupTag(attr);
+ if (group)
+ printf(" %s:\n", ippTagString(group));
+ }
+
+ if ((name = ippGetName(attr)) != NULL)
+ {
+ ippAttributeString(attr, buffer, sizeof(buffer));
+ printf(" %s(%s%s)=%s\n", name, ippGetCount(attr) > 1 ? "1setOf " : "", ippTagString(ippGetValueTag(attr)), buffer);
+ }
+ }
+}
+
+
+/*
+ * 'show_capabilities()' - Show printer capabilities.
+ */
+
+static void
+show_capabilities(ipp_t *response) /* I - Printer attributes */
+{
+ int i; /* Looping var */
+ ipp_attribute_t *attr; /* Attribute */
+ char buffer[1024]; /* Attribute value buffer */
+ static const char * const pattrs[] = /* Attributes we want to show */
+ {
+ "copies-default",
+ "copies-supported",
+ "finishings-default",
+ "finishings-ready",
+ "finishings-supported",
+ "media-default",
+ "media-ready",
+ "media-supported",
+ "output-bin-default",
+ "output-bin-supported",
+ "print-color-mode-default",
+ "print-color-mode-supported",
+ "sides-default",
+ "sides-supported",
+ "document-format-default",
+ "document-format-supported",
+ "pwg-raster-document-resolution-supported",
+ "pwg-raster-document-type-supported",
+ "urf-supported"
+ };
+
+
+ puts("CAPABILITIES:");
+ for (i = 0; i < (int)(sizeof(pattrs) / sizeof(pattrs[0])); i ++)
+ {
+ if ((attr = ippFindAttribute(response, pattrs[i], IPP_TAG_ZERO)) != NULL)
+ {
+ ippAttributeString(attr, buffer, sizeof(buffer));
+ printf(" %s=%s\n", pattrs[i], buffer);
+ }
+ }
+}
+
+
+/*
+ * 'usage()' - Show program usage...
+ */
+
+static void
+usage(void)
+{
+ puts("Usage: ./testclient printer-uri [options]");
+ puts("Options:");
+ puts(" -d document-format Generate the specified format");
+ puts(" -f print-file Print the named file");
+ puts(" -g Force grayscale printing");
+ puts(" -k Keep temporary files");
+ puts(" -v Be more verbose");
+}
diff --git a/libcups_version b/libcups_version
index 0b1f88b8..437a354a 100644
--- a/libcups_version
+++ b/libcups_version
@@ -1 +1 @@
-v2.2.3
+v2.2.6