summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDidier Raboud <odyx@debian.org>2015-08-19 18:03:33 +0200
committerDidier Raboud <odyx@debian.org>2015-08-18 19:56:55 +0200
commit42ed110d6642370105cb6c3a7e8328012395cab4 (patch)
treea90d25f041d4b5142744f3a83c4994d464afd5fa
parent6d72268775295f02fa162f451dad6551ec868a18 (diff)
Imported Upstream version 1.0.73
-rw-r--r--INSTALL2
-rw-r--r--Makefile.am32
-rw-r--r--Makefile.in130
-rw-r--r--NEWS51
-rw-r--r--README14
-rw-r--r--backend/implicitclass.c248
-rw-r--r--charset/pdf.utf-8.simple4
-rw-r--r--config.h.in18
-rwxr-xr-xconfigure451
-rw-r--r--configure.ac61
-rw-r--r--cupsfilters/attr.c2
-rw-r--r--cupsfilters/cmyk.c2
-rw-r--r--cupsfilters/dither.c2
-rw-r--r--cupsfilters/image-private.h2
-rw-r--r--cupsfilters/raster.c2
-rw-r--r--filter/banner.c2
-rw-r--r--filter/banner.h2
-rw-r--r--filter/bannertopdf.c1
-rw-r--r--filter/foomatic-rip/foomaticrip.c2
-rw-r--r--filter/foomatic-rip/postscript.c2
-rw-r--r--filter/foomatic-rip/process.c1
-rw-r--r--filter/foomatic-rip/renderer.c2
-rw-r--r--filter/gstoraster.c2
-rw-r--r--filter/pdf.cxx2
-rw-r--r--filter/pdftoijs.cxx9
-rw-r--r--filter/pdftoopvp/OPVPOutputDev.cxx6
-rw-r--r--filter/pdftoopvp/oprs/OPRS.cxx4
-rw-r--r--filter/pdftoopvp/pdftoopvp.cxx8
-rw-r--r--filter/pdftops.c2
-rw-r--r--filter/pdftoraster.cxx11
-rw-r--r--filter/pdfutils.c1
-rw-r--r--filter/rastertoescpx.c16
-rw-r--r--filter/sys5ippprinter.c2
-rw-r--r--filter/urftopdf.cpp3
-rw-r--r--fontembed/embed_pdf.h4
-rw-r--r--fontembed/main.c5
-rw-r--r--utils/cups-browsed.814
-rw-r--r--utils/cups-browsed.c1711
-rw-r--r--utils/cups-browsed.conf.524
-rw-r--r--utils/cups-browsed.conf.in13
-rw-r--r--utils/org.cups.cupsd.Notifier.xml147
41 files changed, 2855 insertions, 162 deletions
diff --git a/INSTALL b/INSTALL
index 6022924e8..dd7304876 100644
--- a/INSTALL
+++ b/INSTALL
@@ -1,4 +1,4 @@
-INSTALL - OpenPrinting CUPS Filters v1.0.71 - 2015-07-02
+INSTALL - OpenPrinting CUPS Filters v1.0.73 - 2015-08-18
--------------------------------------------------------
This file describes how to compile and install OpenPrinting CUPS
diff --git a/Makefile.am b/Makefile.am
index 3e3826918..b5fa96160 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -24,7 +24,7 @@ EXTRA_DIST = \
# Backends
# ========
pkgbackenddir = $(CUPS_SERVERBIN)/backend
-pkgbackend_PROGRAMS = parallel serial
+pkgbackend_PROGRAMS = parallel serial implicitclass
check_PROGRAMS = test1284
# We need ieee1284 up and running.
@@ -44,6 +44,12 @@ serial_SOURCES = \
serial_LDADD = $(CUPS_LIBS)
serial_CFLAGS = $(CUPS_CFLAGS)
+implicitclass_SOURCES = \
+ backend/backend-private.h \
+ backend/implicitclass.c
+implicitclass_LDADD = $(CUPS_LIBS)
+implicitclass_CFLAGS = $(CUPS_CFLAGS)
+
test1284_SOURCES = \
backend/backend-private.h \
backend/ieee1284.c \
@@ -716,23 +722,38 @@ EXTRA_DIST += \
# UTILS
# =====
+cups_notifier_sources = \
+ cups-notifier.c \
+ cups-notifier.h
+
+$(cups_notifier_sources): utils/org.cups.cupsd.Notifier.xml
+ gdbus-codegen \
+ --interface-prefix org.cups.cupsd \
+ --c-namespace Cups \
+ --generate-c-code cups-notifier \
+ $^
+
sbin_PROGRAMS = \
cups-browsed
cups_browsed_SOURCES = \
utils/cups-browsed.c
+nodist_cups_browsed_SOURCES = \
+ $(cups_notifier_sources)
cups_browsed_CFLAGS = \
$(CUPS_CFLAGS) \
$(AVAHI_CFLAGS) \
$(AVAHI_GLIB_CFLAGS) \
$(GLIB_CFLAGS) \
- $(GIO_CFLAGS)
+ $(GIO_CFLAGS) \
+ $(GIO_UNIX_CFLAGS)
cups_browsed_CXXFLAGS = $(cups_browsed_CFLAGS)
cups_browsed_LDADD = \
$(CUPS_LIBS) \
$(AVAHI_LIBS) \
$(AVAHI_GLIB_LIBS) \
$(GLIB_LIBS) \
- $(GIO_LIBS)
+ $(GIO_LIBS) \
+ $(GIO_UNIX_LIBS)
initrcdir = $(INITDDIR)
initrc_SCRIPTS = utils/cups-browsed
man_MANS = \
@@ -740,7 +761,10 @@ man_MANS = \
utils/cups-browsed.conf.5 \
filter/foomatic-rip/foomatic-rip.1
EXTRA_DIST += utils/cups-browsed.in \
- $(man_MANS)
+ $(man_MANS) \
+ utils/org.cups.cupsd.Notifier.xml
+BUILT_SOURCES = $(cups_notifier_sources)
+CLEANFILES = $(BUILT_SOURCES)
# ===
# PPD
diff --git a/Makefile.in b/Makefile.in
index 69a095093..d257f08db 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -81,7 +81,8 @@ PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
-pkgbackend_PROGRAMS = parallel$(EXEEXT) serial$(EXEEXT)
+pkgbackend_PROGRAMS = parallel$(EXEEXT) serial$(EXEEXT) \
+ implicitclass$(EXEEXT)
check_PROGRAMS = test1284$(EXEEXT) testcmyk$(EXEEXT) \
testdither$(EXEEXT) testimage$(EXEEXT) testrgb$(EXEEXT) \
test_analyze$(EXEEXT) test_pdf$(EXEEXT) test_ps$(EXEEXT) \
@@ -247,10 +248,14 @@ commandtopclx_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(commandtopclx_CFLAGS) \
$(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
am_cups_browsed_OBJECTS = cups_browsed-cups-browsed.$(OBJEXT)
-cups_browsed_OBJECTS = $(am_cups_browsed_OBJECTS)
+am__objects_2 = cups_browsed-cups-notifier.$(OBJEXT)
+nodist_cups_browsed_OBJECTS = $(am__objects_2)
+cups_browsed_OBJECTS = $(am_cups_browsed_OBJECTS) \
+ $(nodist_cups_browsed_OBJECTS)
cups_browsed_DEPENDENCIES = $(am__DEPENDENCIES_1) \
$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
- $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
+ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1)
cups_browsed_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(cups_browsed_CFLAGS) \
$(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
@@ -285,6 +290,12 @@ imagetoraster_DEPENDENCIES = $(am__DEPENDENCIES_1) libcupsfilters.la
imagetoraster_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(imagetoraster_CFLAGS) \
$(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+am_implicitclass_OBJECTS = implicitclass-implicitclass.$(OBJEXT)
+implicitclass_OBJECTS = $(am_implicitclass_OBJECTS)
+implicitclass_DEPENDENCIES = $(am__DEPENDENCIES_1)
+implicitclass_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(implicitclass_CFLAGS) \
+ $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
am_parallel_OBJECTS = parallel-ieee1284.$(OBJEXT) \
parallel-parallel.$(OBJEXT)
parallel_OBJECTS = $(am_parallel_OBJECTS)
@@ -498,8 +509,9 @@ SOURCES = $(libcupsfilters_la_SOURCES) $(libfontembed_la_SOURCES) \
$(libphpcups_la_SOURCES) $(bannertopdf_SOURCES) \
$(EXTRA_bannertopdf_SOURCES) $(commandtoescpx_SOURCES) \
$(commandtopclx_SOURCES) $(cups_browsed_SOURCES) \
- $(foomatic_rip_SOURCES) $(gstoraster_SOURCES) \
- $(imagetopdf_SOURCES) $(imagetoraster_SOURCES) \
+ $(nodist_cups_browsed_SOURCES) $(foomatic_rip_SOURCES) \
+ $(gstoraster_SOURCES) $(imagetopdf_SOURCES) \
+ $(imagetoraster_SOURCES) $(implicitclass_SOURCES) \
$(parallel_SOURCES) $(pdftoijs_SOURCES) $(pdftoopvp_SOURCES) \
$(pdftopdf_SOURCES) $(pdftops_SOURCES) \
$(EXTRA_pdftops_SOURCES) $(pdftoraster_SOURCES) \
@@ -517,17 +529,18 @@ DIST_SOURCES = $(libcupsfilters_la_SOURCES) $(libfontembed_la_SOURCES) \
$(commandtopclx_SOURCES) $(cups_browsed_SOURCES) \
$(foomatic_rip_SOURCES) $(gstoraster_SOURCES) \
$(imagetopdf_SOURCES) $(imagetoraster_SOURCES) \
- $(parallel_SOURCES) $(pdftoijs_SOURCES) $(pdftoopvp_SOURCES) \
- $(pdftopdf_SOURCES) $(pdftops_SOURCES) \
- $(EXTRA_pdftops_SOURCES) $(pdftoraster_SOURCES) \
- $(rastertoescpx_SOURCES) $(rastertopclx_SOURCES) \
- $(rastertopdf_SOURCES) $(serial_SOURCES) \
- $(sys5ippprinter_SOURCES) $(EXTRA_sys5ippprinter_SOURCES) \
- $(test1284_SOURCES) $(test_analyze_SOURCES) \
- $(test_pdf_SOURCES) $(test_pdf1_SOURCES) $(test_pdf2_SOURCES) \
- $(test_ps_SOURCES) $(testcmyk_SOURCES) $(testdither_SOURCES) \
- $(testimage_SOURCES) $(testrgb_SOURCES) $(texttopdf_SOURCES) \
- $(ttfread_SOURCES) $(urftopdf_SOURCES)
+ $(implicitclass_SOURCES) $(parallel_SOURCES) \
+ $(pdftoijs_SOURCES) $(pdftoopvp_SOURCES) $(pdftopdf_SOURCES) \
+ $(pdftops_SOURCES) $(EXTRA_pdftops_SOURCES) \
+ $(pdftoraster_SOURCES) $(rastertoescpx_SOURCES) \
+ $(rastertopclx_SOURCES) $(rastertopdf_SOURCES) \
+ $(serial_SOURCES) $(sys5ippprinter_SOURCES) \
+ $(EXTRA_sys5ippprinter_SOURCES) $(test1284_SOURCES) \
+ $(test_analyze_SOURCES) $(test_pdf_SOURCES) \
+ $(test_pdf1_SOURCES) $(test_pdf2_SOURCES) $(test_ps_SOURCES) \
+ $(testcmyk_SOURCES) $(testdither_SOURCES) $(testimage_SOURCES) \
+ $(testrgb_SOURCES) $(texttopdf_SOURCES) $(ttfread_SOURCES) \
+ $(urftopdf_SOURCES)
am__can_run_installinfo = \
case $$AM_UPDATE_INFO_DIR in \
n|no|NO) false;; \
@@ -817,6 +830,8 @@ FREETYPE_LIBS = @FREETYPE_LIBS@
GETLINE = @GETLINE@
GIO_CFLAGS = @GIO_CFLAGS@
GIO_LIBS = @GIO_LIBS@
+GIO_UNIX_CFLAGS = @GIO_UNIX_CFLAGS@
+GIO_UNIX_LIBS = @GIO_UNIX_LIBS@
GLIB_CFLAGS = @GLIB_CFLAGS@
GLIB_LIBS = @GLIB_LIBS@
GREP = @GREP@
@@ -961,7 +976,8 @@ EXTRA_DIST = $(doc_DATA) autogen.sh libcupsfilters.pc.in \
$(pkgcupsdata_DATA) $(pkgdriver_DATA) $(pkgppdc_DATA) \
$(pkgmime_DATA) $(pkgfontembedinclude_DATA) fontembed/README \
$(pkgfontconfig_DATA) $(pkgfilter_SCRIPTS) filter/test.sh \
- utils/cups-browsed.in $(man_MANS) $(ppd_DATA) scripting/perl \
+ utils/cups-browsed.in $(man_MANS) \
+ utils/org.cups.cupsd.Notifier.xml $(ppd_DATA) scripting/perl \
scripting/php/README scripting/php/phpcups.php
# ========
@@ -984,6 +1000,12 @@ serial_SOURCES = \
serial_LDADD = $(CUPS_LIBS)
serial_CFLAGS = $(CUPS_CFLAGS)
+implicitclass_SOURCES = \
+ backend/backend-private.h \
+ backend/implicitclass.c
+
+implicitclass_LDADD = $(CUPS_LIBS)
+implicitclass_CFLAGS = $(CUPS_CFLAGS)
test1284_SOURCES = \
backend/backend-private.h \
backend/ieee1284.c \
@@ -1595,15 +1617,27 @@ texttopdf_LDADD = \
$(FONTCONFIG_LIBS) \
libfontembed.la
+
+# =====
+# UTILS
+# =====
+cups_notifier_sources = \
+ cups-notifier.c \
+ cups-notifier.h
+
cups_browsed_SOURCES = \
utils/cups-browsed.c
+nodist_cups_browsed_SOURCES = \
+ $(cups_notifier_sources)
+
cups_browsed_CFLAGS = \
$(CUPS_CFLAGS) \
$(AVAHI_CFLAGS) \
$(AVAHI_GLIB_CFLAGS) \
$(GLIB_CFLAGS) \
- $(GIO_CFLAGS)
+ $(GIO_CFLAGS) \
+ $(GIO_UNIX_CFLAGS)
cups_browsed_CXXFLAGS = $(cups_browsed_CFLAGS)
cups_browsed_LDADD = \
@@ -1611,7 +1645,8 @@ cups_browsed_LDADD = \
$(AVAHI_LIBS) \
$(AVAHI_GLIB_LIBS) \
$(GLIB_LIBS) \
- $(GIO_LIBS)
+ $(GIO_LIBS) \
+ $(GIO_UNIX_LIBS)
initrcdir = $(INITDDIR)
initrc_SCRIPTS = utils/cups-browsed
@@ -1620,6 +1655,8 @@ man_MANS = \
utils/cups-browsed.conf.5 \
filter/foomatic-rip/foomatic-rip.1
+BUILT_SOURCES = $(cups_notifier_sources)
+CLEANFILES = $(BUILT_SOURCES)
# ===
# PPD
@@ -1648,7 +1685,7 @@ ppd_DATA = \
@WITH_PHP_TRUE@libphpcups_la_LIBADD = $(CUPS_LIBS)
@WITH_PHP_TRUE@libphpcups_la_CFLAGS = $(CUPS_CFLAGS)
@WITH_PHP_TRUE@libphpcups_la_LDFLAGS = -no-undefined
-all: config.h
+all: $(BUILT_SOURCES) config.h
$(MAKE) $(AM_MAKEFLAGS) all-am
.SUFFIXES:
@@ -2031,6 +2068,10 @@ imagetoraster$(EXEEXT): $(imagetoraster_OBJECTS) $(imagetoraster_DEPENDENCIES) $
@rm -f imagetoraster$(EXEEXT)
$(AM_V_CCLD)$(imagetoraster_LINK) $(imagetoraster_OBJECTS) $(imagetoraster_LDADD) $(LIBS)
+implicitclass$(EXEEXT): $(implicitclass_OBJECTS) $(implicitclass_DEPENDENCIES) $(EXTRA_implicitclass_DEPENDENCIES)
+ @rm -f implicitclass$(EXEEXT)
+ $(AM_V_CCLD)$(implicitclass_LINK) $(implicitclass_OBJECTS) $(implicitclass_LDADD) $(LIBS)
+
parallel$(EXEEXT): $(parallel_OBJECTS) $(parallel_DEPENDENCIES) $(EXTRA_parallel_DEPENDENCIES)
@rm -f parallel$(EXEEXT)
$(AM_V_CCLD)$(parallel_LINK) $(parallel_OBJECTS) $(parallel_LDADD) $(LIBS)
@@ -2211,6 +2252,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/commandtoescpx-commandtoescpx.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/commandtopclx-commandtopclx.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cups_browsed-cups-browsed.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cups_browsed-cups-notifier.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dynstring.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/embed.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/embed_pdf.Plo@am__quote@
@@ -2230,6 +2272,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/imagetopdf-imagetopdf.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/imagetoraster-common.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/imagetoraster-imagetoraster.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/implicitclass-implicitclass.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcupsfilters_la-attr.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcupsfilters_la-check.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcupsfilters_la-cmyk.Plo@am__quote@
@@ -2664,6 +2707,20 @@ cups_browsed-cups-browsed.obj: utils/cups-browsed.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(cups_browsed_CFLAGS) $(CFLAGS) -c -o cups_browsed-cups-browsed.obj `if test -f 'utils/cups-browsed.c'; then $(CYGPATH_W) 'utils/cups-browsed.c'; else $(CYGPATH_W) '$(srcdir)/utils/cups-browsed.c'; fi`
+cups_browsed-cups-notifier.o: cups-notifier.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(cups_browsed_CFLAGS) $(CFLAGS) -MT cups_browsed-cups-notifier.o -MD -MP -MF $(DEPDIR)/cups_browsed-cups-notifier.Tpo -c -o cups_browsed-cups-notifier.o `test -f 'cups-notifier.c' || echo '$(srcdir)/'`cups-notifier.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/cups_browsed-cups-notifier.Tpo $(DEPDIR)/cups_browsed-cups-notifier.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cups-notifier.c' object='cups_browsed-cups-notifier.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(cups_browsed_CFLAGS) $(CFLAGS) -c -o cups_browsed-cups-notifier.o `test -f 'cups-notifier.c' || echo '$(srcdir)/'`cups-notifier.c
+
+cups_browsed-cups-notifier.obj: cups-notifier.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(cups_browsed_CFLAGS) $(CFLAGS) -MT cups_browsed-cups-notifier.obj -MD -MP -MF $(DEPDIR)/cups_browsed-cups-notifier.Tpo -c -o cups_browsed-cups-notifier.obj `if test -f 'cups-notifier.c'; then $(CYGPATH_W) 'cups-notifier.c'; else $(CYGPATH_W) '$(srcdir)/cups-notifier.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/cups_browsed-cups-notifier.Tpo $(DEPDIR)/cups_browsed-cups-notifier.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cups-notifier.c' object='cups_browsed-cups-notifier.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(cups_browsed_CFLAGS) $(CFLAGS) -c -o cups_browsed-cups-notifier.obj `if test -f 'cups-notifier.c'; then $(CYGPATH_W) 'cups-notifier.c'; else $(CYGPATH_W) '$(srcdir)/cups-notifier.c'; fi`
+
foomatic_rip-foomaticrip.o: filter/foomatic-rip/foomaticrip.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(foomatic_rip_CFLAGS) $(CFLAGS) -MT foomatic_rip-foomaticrip.o -MD -MP -MF $(DEPDIR)/foomatic_rip-foomaticrip.Tpo -c -o foomatic_rip-foomaticrip.o `test -f 'filter/foomatic-rip/foomaticrip.c' || echo '$(srcdir)/'`filter/foomatic-rip/foomaticrip.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/foomatic_rip-foomaticrip.Tpo $(DEPDIR)/foomatic_rip-foomaticrip.Po
@@ -2846,6 +2903,20 @@ imagetoraster-imagetoraster.obj: filter/imagetoraster.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(imagetoraster_CFLAGS) $(CFLAGS) -c -o imagetoraster-imagetoraster.obj `if test -f 'filter/imagetoraster.c'; then $(CYGPATH_W) 'filter/imagetoraster.c'; else $(CYGPATH_W) '$(srcdir)/filter/imagetoraster.c'; fi`
+implicitclass-implicitclass.o: backend/implicitclass.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(implicitclass_CFLAGS) $(CFLAGS) -MT implicitclass-implicitclass.o -MD -MP -MF $(DEPDIR)/implicitclass-implicitclass.Tpo -c -o implicitclass-implicitclass.o `test -f 'backend/implicitclass.c' || echo '$(srcdir)/'`backend/implicitclass.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/implicitclass-implicitclass.Tpo $(DEPDIR)/implicitclass-implicitclass.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='backend/implicitclass.c' object='implicitclass-implicitclass.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(implicitclass_CFLAGS) $(CFLAGS) -c -o implicitclass-implicitclass.o `test -f 'backend/implicitclass.c' || echo '$(srcdir)/'`backend/implicitclass.c
+
+implicitclass-implicitclass.obj: backend/implicitclass.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(implicitclass_CFLAGS) $(CFLAGS) -MT implicitclass-implicitclass.obj -MD -MP -MF $(DEPDIR)/implicitclass-implicitclass.Tpo -c -o implicitclass-implicitclass.obj `if test -f 'backend/implicitclass.c'; then $(CYGPATH_W) 'backend/implicitclass.c'; else $(CYGPATH_W) '$(srcdir)/backend/implicitclass.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/implicitclass-implicitclass.Tpo $(DEPDIR)/implicitclass-implicitclass.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='backend/implicitclass.c' object='implicitclass-implicitclass.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(implicitclass_CFLAGS) $(CFLAGS) -c -o implicitclass-implicitclass.obj `if test -f 'backend/implicitclass.c'; then $(CYGPATH_W) 'backend/implicitclass.c'; else $(CYGPATH_W) '$(srcdir)/backend/implicitclass.c'; fi`
+
parallel-ieee1284.o: backend/ieee1284.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(parallel_CFLAGS) $(CFLAGS) -MT parallel-ieee1284.o -MD -MP -MF $(DEPDIR)/parallel-ieee1284.Tpo -c -o parallel-ieee1284.o `test -f 'backend/ieee1284.c' || echo '$(srcdir)/'`backend/ieee1284.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/parallel-ieee1284.Tpo $(DEPDIR)/parallel-ieee1284.Po
@@ -4525,7 +4596,8 @@ distcleancheck: distclean
check-am: all-am
$(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS)
$(MAKE) $(AM_MAKEFLAGS) check-TESTS
-check: check-am
+check: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) check-am
all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(SCRIPTS) $(MANS) $(DATA) \
config.h
install-binPROGRAMS: install-libLTLIBRARIES
@@ -4534,7 +4606,8 @@ installdirs:
for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(phpextensiondir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(pkgbackenddir)" "$(DESTDIR)$(pkgfilterdir)" "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(initrcdir)" "$(DESTDIR)$(pkgfilterdir)" "$(DESTDIR)$(man1dir)" "$(DESTDIR)$(man5dir)" "$(DESTDIR)$(man8dir)" "$(DESTDIR)$(docdir)" "$(DESTDIR)$(pkgbannerdir)" "$(DESTDIR)$(pkgcharsetdir)" "$(DESTDIR)$(pkgconfdir)" "$(DESTDIR)$(pkgcupsdatadir)" "$(DESTDIR)$(pkgcupsserverrootdir)" "$(DESTDIR)$(pkgdriverdir)" "$(DESTDIR)$(pkgfiltersincludedir)" "$(DESTDIR)$(pkgfontconfigdir)" "$(DESTDIR)$(pkgfontembedincludedir)" "$(DESTDIR)$(pkgmimedir)" "$(DESTDIR)$(pkgppdcdir)" "$(DESTDIR)$(ppddir)"; do \
test -z "$$dir" || $(MKDIR_P) "$$dir"; \
done
-install: install-am
+install: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) install-am
install-exec: install-exec-am
install-data: install-data-am
uninstall: uninstall-am
@@ -4559,6 +4632,7 @@ mostlyclean-generic:
-test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG)
clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
distclean-generic:
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
@@ -4567,6 +4641,7 @@ distclean-generic:
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
+ -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
clean: clean-am
clean-am: clean-binPROGRAMS clean-checkPROGRAMS clean-generic \
@@ -4666,8 +4741,8 @@ uninstall-am: uninstall-binPROGRAMS uninstall-docDATA \
$(MAKE) $(AM_MAKEFLAGS) uninstall-hook
uninstall-man: uninstall-man1 uninstall-man5 uninstall-man8
-.MAKE: all check-am install-am install-data-am install-exec-am \
- install-strip uninstall-am
+.MAKE: all check check-am install install-am install-data-am \
+ install-exec-am install-strip uninstall-am
.PHONY: CTAGS GTAGS TAGS all all-am am--refresh check check-TESTS \
check-am clean clean-binPROGRAMS clean-checkPROGRAMS \
@@ -4711,6 +4786,13 @@ uninstall-man: uninstall-man1 uninstall-man5 uninstall-man8
uninstall-pkgppdcDATA uninstall-ppdDATA uninstall-sbinPROGRAMS
+$(cups_notifier_sources): utils/org.cups.cupsd.Notifier.xml
+ gdbus-codegen \
+ --interface-prefix org.cups.cupsd \
+ --c-namespace Cups \
+ --generate-c-code cups-notifier \
+ $^
+
distclean-local:
rm -rf *.cache *~
diff --git a/NEWS b/NEWS
index 3d4af8d52..6195b5202 100644
--- a/NEWS
+++ b/NEWS
@@ -1,15 +1,60 @@
-NEWS - OpenPrinting CUPS Filters v1.0.71 - 2015-07-02
+NEWS - OpenPrinting CUPS Filters v1.0.73 - 2015-08-18
-----------------------------------------------------
+CHANGES IN V1.0.73
+
+ - cups-browsed: Added missing
+ utils/org.cups.cupsd.Notifier.xml file.
+
+CHANGES IN V1.0.72
+
+ - cups-browsed, implicitclass: Added load balancing
+ functionality. If there are several remote CUPS printers
+ with the same name, they for locally a cluster represented
+ by a print queue with this name. This printer prints through
+ a special backend (implicitclass) which makes cups-browsed
+ find the best destination remote queue (fewest jobs,
+ enabled) for this job.
+ - cups-browsed: Added protection against accidental deletion of
+ print queues generated by cups-browsed. These queues now get
+ automatically re-created.
+ - cups-browsed: Added LDAP support. Appropriately configured via
+ cups-browsed.conf remote printers made available via LDAP will be
+ looked up and local queues pointing to them created. Thanks to
+ Raphael Geissert (atomo64 at gmail dot com) for contributing this
+ patch (Debian bug #795185).
+ - cups-browsed: Introduced new handling for the default
+ printer using cache files. So we do not need to keep an auto-generated
+ queue because it is set as default printer. If the auto-generated
+ queue disappears, the old local printer is set as default again and
+ when it re-appears it returns to be the default printer.
+ - cups-browsed: Added infrastructure for subscribing to CUPS
+ notifications for things like improved default printer handling,
+ load balancing, ...
+ - foomatic-rip: Prevent crash when supplying "media" option with empty
+ value ("media=", Ubuntu bug #1479871).
+ - pdftoopvp: Adaptations to API changes on Poppler 0.34.0, note that
+ this patch disables color management in this filter. Thanks to
+ Vincent le Garrec and Andreas K. Huettel for the patch (Bug #1301,
+ Gentoo bug #554782).
+ - libcupsfilters, bannertopdf, foomatic-rip, gstoraster, pdftoijs,
+ sys5ippprinter, pdftoopvp, pdftops, pdftoraster, rastertoescpx,
+ urftopdf, texttopdf: Miscellaneous fixes for build compatibility with
+ different platforms, like config.h as very first include and so on.
+ Thanks to Richard Palo for the patch (Bug #1264).
+ - texttopdf: Request the generic 'monospace' font alias from fontconfig
+ instead of the hard-coded FreeMono. Thanks to Fabian Greffrath
+ (fabian at debian dot org) for the patch (Debian bug #788048).
+
CHANGES IN V1.0.71
- texttopdf: The Page allocation is moved into textcommon.c, where it
does all the necessary checking: lower-bounds for CVE-2015-3258 and
- upper-bounds for CVE-2015-3259 due to integer overflows for the
+ upper-bounds for CVE-2015-3279 due to integer overflows for the
calloc() call initialising Page[0] and the memset() call in
texttopdf.c's WritePage() function zeroing the entire array. Thanks
to Tim Waugh from Red Hat for the patch.
- - texttopdf: Upper-bounds checking (CVE-2015-3259).
+ - texttopdf: Upper-bounds checking (CVE-2015-3279).
CHANGES IN V1.0.70
diff --git a/README b/README
index dbe7c97d6..ec9c508b5 100644
--- a/README
+++ b/README
@@ -1,4 +1,4 @@
-README - OpenPrinting CUPS Filters v1.0.71 - 2015-07-02
+README - OpenPrinting CUPS Filters v1.0.73 - 2015-08-18
-------------------------------------------------------
Looking for compile instructions? Read the file "INSTALL.txt"
@@ -223,11 +223,13 @@ HELPER DAEMON FOR BROWSING REMOTE CUPS PRINTERS AND IPP NETWORK PRINTERS
Also high availability with redundant print servers is
supported. If there is more than one server providing a shared
- print queue with the same name, cups-browsed uses the first queue
- which appeared and if this queue disappears, cups-browsed
- seamlessly switches to the queue of another server. Unfortunately,
- load-balancing (what CUPS did via implicit classes) is not
- possible with cups-browsed.
+ print queue with the same name, cups-browsed forms a cluster
+ locally with this name as queue name and printing through
+ the "implicitclass" backend. Each job triggers cups-browsed
+ to check which remote queue is the best for the job, meaning
+ that it is enabled and has the fewest jobs of all queues in the
+ cluster. This makes all queues/printers equally used. This is
+ also what CUPS formerly did with implicit classes.
For maximum security cups-browsed uses IPPS (encrypted IPP)
whenever possible.
diff --git a/backend/implicitclass.c b/backend/implicitclass.c
new file mode 100644
index 000000000..e842b9f34
--- /dev/null
+++ b/backend/implicitclass.c
@@ -0,0 +1,248 @@
+/*
+ * "$Id$"
+ *
+ * DNS-SD discovery backend for CUPS.
+ *
+ * Copyright 2008-2015 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"
+ * "LICENSE" 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 "backend-private.h"
+#include <cups/array.h>
+#include <ctype.h>
+
+/*
+ * Local globals...
+ */
+
+#define IMPLICIT_CLASS_DEST_HOST_FILE "/var/cache/cups/cups-browsed-dest-host-%s"
+static int job_canceled = 0;
+ /* Set to 1 on SIGTERM */
+
+/*
+ * Local functions... */
+
+static void sigterm_handler(int sig);
+
+
+/*
+ * 'main()' - Browse for printers.
+ */
+
+int /* O - Exit status */
+main(int argc, /* I - Number of command-line args */
+ char *argv[]) /* I - Command-line arguments */
+{
+ const char *device_uri; /* URI with which we were called */
+ char queue_name[1024],
+ filename[1024];
+ FILE *fp;
+ char *ptr1, *ptr2;
+ int i, n;
+ char dest_host[1024]; /* Destination host */
+#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
+ struct sigaction action; /* Actions for POSIX signals */
+#endif /* HAVE_SIGACTION && !HAVE_SIGSET */
+
+ /*
+ * Don't buffer stderr, and catch SIGTERM...
+ */
+
+ setbuf(stderr, NULL);
+
+#ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */
+ sigset(SIGTERM, sigterm_handler);
+#elif defined(HAVE_SIGACTION)
+ memset(&action, 0, sizeof(action));
+
+ sigemptyset(&action.sa_mask);
+ action.sa_handler = sigterm_handler;
+ sigaction(SIGTERM, &action, NULL);
+#else
+ signal(SIGTERM, sigterm_handler);
+#endif /* HAVE_SIGSET */
+
+ /*
+ * Check command-line...
+ */
+
+ if (argc >= 6)
+ {
+ if ((device_uri = getenv("DEVICE_URI")) == NULL)
+ {
+ if (!argv || !argv[0] || !strchr(argv[0], ':'))
+ return (-1);
+
+ device_uri = argv[0];
+ }
+ if ((ptr1 = strchr(device_uri, ':')) == NULL) {
+ }
+ ptr1 ++;
+ strncpy(queue_name, ptr1, sizeof(queue_name));
+ snprintf(filename, sizeof(filename), IMPLICIT_CLASS_DEST_HOST_FILE,
+ queue_name);
+ for (i = 0; i < 40; i++) {
+ /* Wait up to 20 sec for cups-browsed to supply the destination host */
+ /* Try reading the file where cups-browsed has deposited the destination
+ host */
+ fp = fopen(filename, "r");
+ if (fp == NULL)
+ goto failed;
+ ptr1 = dest_host;
+ /* Destination host is between double quotes, as double quotes are
+ illegal in host names one easily recognizes whether the file is
+ complete and avoids accepting a partially written host name */
+ n = fscanf(fp, "\"%s", ptr1);
+ fclose(fp);
+ if (n == 1 && strlen(ptr1) > 0) {
+ if ((ptr2 = strchr((const char *)ptr1, '"')) != NULL) {
+ *ptr2 = '\0';
+ break;
+ }
+ }
+ failed:
+ /* Pause half a second before next attempt */
+ usleep(500000);
+ }
+
+ /* Delete host name file after having read it once, so that we wait for
+ cups-browsed's decision again on the next job */
+ unlink(filename);
+
+ if (i >= 40) {
+ /* Timeout, no useful data from cups-browsed received */
+ fprintf(stderr, "ERROR: No destination host name supplied by cups-browsed for printer \"%s\", is cups-browsed running?\n",
+ queue_name);
+ exit(CUPS_BACKEND_RETRY);
+ }
+
+ /* We have the destination host name now, do the job */
+ if (strcmp(dest_host, "NO_DEST_FOUND")) {
+ char server_str[1024];
+ const char *title;
+ int num_options = 0;
+ cups_option_t *options = NULL;
+ int fd, job_id;
+ char buffer[8192];
+
+ fprintf(stderr, "DEBUG: Received destination host name from cups-browsed: %s\n",
+ dest_host);
+ /* Instead of fdeeding the job into the IPP backend, we re-print it into
+ the server's CUPS queue. This way the job gets spooled on the server
+ and we are not blocked until the job is printed. So a subsequent job
+ will be immediately processed and sent out to another server */
+ /* Set destination server */
+ snprintf(server_str, sizeof(server_str), "%s:%d", dest_host,
+ ippPort());
+ cupsSetServer(server_str);
+ /* Parse the command line option and prepare them for the new print
+ job */
+ cupsSetUser(argv[2]);
+ title = argv[3];
+ if (title == NULL)
+ {
+ if (argc == 7) {
+ if ((title = strrchr(argv[6], '/')) != NULL)
+ title ++;
+ else
+ title = argv[6];
+ } else
+ title = "(stdin)";
+ }
+ num_options = cupsAddOption("copies", argv[4], num_options, &options);
+ num_options = cupsParseOptions(argv[5], num_options, &options);
+ if (argc == 7)
+ fd = open(argv[6], O_RDONLY);
+ else
+ fd = 0; /* stdin */
+
+ /* Queue the job directly on the server */
+ if ((job_id = cupsCreateJob(CUPS_HTTP_DEFAULT, queue_name,
+ title ? title : "(stdin)",
+ num_options, options)) > 0) {
+ http_status_t status; /* Write status */
+ const char *format; /* Document format */
+ ssize_t bytes; /* Bytes read */
+
+ if (cupsGetOption("raw", num_options, options))
+ format = CUPS_FORMAT_RAW;
+ else if ((format = cupsGetOption("document-format", num_options,
+ options)) == NULL)
+ format = CUPS_FORMAT_AUTO;
+
+ status = cupsStartDocument(CUPS_HTTP_DEFAULT, queue_name, job_id, NULL,
+ format, 1);
+
+ while (status == HTTP_CONTINUE &&
+ (bytes = read(fd, buffer, sizeof(buffer))) > 0)
+ status = cupsWriteRequestData(CUPS_HTTP_DEFAULT, buffer, (size_t)bytes);
+
+ if (status != HTTP_CONTINUE) {
+ fprintf(stderr, "%s: Error - unable to queue the print data - %s.",
+ argv[0], httpStatus(status));
+ cupsFinishDocument(CUPS_HTTP_DEFAULT, queue_name);
+ cupsCancelJob2(CUPS_HTTP_DEFAULT, queue_name, job_id, 0);
+ return (1);
+ }
+
+ if (cupsFinishDocument(CUPS_HTTP_DEFAULT, queue_name) != IPP_OK) {
+ fprintf(stderr, "%s: %s", argv[0], cupsLastErrorString());
+ cupsCancelJob2(CUPS_HTTP_DEFAULT, queue_name, job_id, 0);
+ return (1);
+ }
+ }
+
+ if (job_id < 1) {
+ fprintf(stderr, "%s: %s", argv[0], cupsLastErrorString());
+ return (1);
+ }
+
+ return (0);
+
+ } else {
+ fprintf(stderr, "ERROR: No suitable destination host found by cups-browsed.\n");
+ exit(CUPS_BACKEND_RETRY);
+ }
+ }
+ else if (argc != 1)
+ {
+ fprintf(stderr,
+ "Usage: %s job-id user title copies options [file]",
+ argv[0]);
+ return (1);
+ }
+
+ /*
+ * No discovery mode at all for this backend
+ */
+
+ return (CUPS_BACKEND_OK);
+}
+
+
+/*
+ * 'sigterm_handler()' - Handle termination signals.
+ */
+
+static void
+sigterm_handler(int sig) /* I - Signal number (unused) */
+{
+ (void)sig;
+
+ if (job_canceled)
+ _exit(CUPS_BACKEND_OK);
+ else
+ job_canceled = 1;
+}
+
diff --git a/charset/pdf.utf-8.simple b/charset/pdf.utf-8.simple
index c1c3d688b..1280f25c8 100644
--- a/charset/pdf.utf-8.simple
+++ b/charset/pdf.utf-8.simple
@@ -28,5 +28,5 @@ charset utf8
# printing.
#
-0000 04FF ltor single FreeMono FreeMono:bold FreeMono:oblique FreeMono:bold:oblique
-0500 05FF rtol single FreeMono
+0000 04FF ltor single monospace monospace:bold monospace:oblique monospace:bold:oblique
+0500 05FF rtol single monospace
diff --git a/config.h.in b/config.h.in
index edf2cab5c..4a56617e8 100644
--- a/config.h.in
+++ b/config.h.in
@@ -78,6 +78,18 @@
/* Define to 1 if you have the <jpeglib.h> header file. */
#undef HAVE_JPEGLIB_H
+/* Define if LDAP support should be enabled */
+#undef HAVE_LDAP
+
+/* If libldap implements ldap_set_rebind_proc */
+#undef HAVE_LDAP_REBIND_PROC
+
+/* If LDAP has SSL/TLS support enabled */
+#undef HAVE_LDAP_SSL
+
+/* Define to 1 if you have the <ldap_ssl.h> header file. */
+#undef HAVE_LDAP_SSL_H
+
/* Defines if we provide jpeg library. */
#undef HAVE_LIBJPEG
@@ -96,6 +108,12 @@
/* Define to 1 if you have the <memory.h> header file. */
#undef HAVE_MEMORY_H
+/* If LDAP support is that of Mozilla */
+#undef HAVE_MOZILLA_LDAP
+
+/* If LDAP support is that of OpenLDAP */
+#undef HAVE_OPENLDAP
+
/* Define to 1 if you have the `open_memstream' function. */
#undef HAVE_OPEN_MEMSTREAM
diff --git a/configure b/configure
index 52a744d22..a8196eaf9 100755
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for cups-filters 1.0.71.
+# Generated by GNU Autoconf 2.69 for cups-filters 1.0.73.
#
#
# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
@@ -587,8 +587,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='cups-filters'
PACKAGE_TARNAME='cups-filters'
-PACKAGE_VERSION='1.0.71'
-PACKAGE_STRING='cups-filters 1.0.71'
+PACKAGE_VERSION='1.0.73'
+PACKAGE_STRING='cups-filters 1.0.73'
PACKAGE_BUGREPORT=''
PACKAGE_URL=''
@@ -668,6 +668,8 @@ INITDIR
RCLINKS_FALSE
RCLINKS_TRUE
BROWSEREMOTEPROTOCOLS
+GIO_UNIX_LIBS
+GIO_UNIX_CFLAGS
GIO_LIBS
GIO_CFLAGS
AVAHI_GLIB_LIBS
@@ -844,6 +846,9 @@ with_tiff
enable_avahi
with_avahi_libs
with_avahi_includes
+enable_ldap
+with_ldap_libs
+with_ldap_includes
with_browseremoteprotocols
with_rcdir
with_rclevels
@@ -887,6 +892,8 @@ AVAHI_GLIB_CFLAGS
AVAHI_GLIB_LIBS
GIO_CFLAGS
GIO_LIBS
+GIO_UNIX_CFLAGS
+GIO_UNIX_LIBS
LCMS_CFLAGS
LCMS_LIBS
FREETYPE_CFLAGS
@@ -1443,7 +1450,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
-\`configure' configures cups-filters 1.0.71 to adapt to many kinds of systems.
+\`configure' configures cups-filters 1.0.73 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1513,7 +1520,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of cups-filters 1.0.71:";;
+ short | recursive ) echo "Configuration of cups-filters 1.0.73:";;
esac
cat <<\_ACEOF
@@ -1534,6 +1541,7 @@ Optional Features:
--disable-libtool-lock avoid locking (might break parallel builds)
--disable-imagefilters Build the image filters.
--disable-avahi Disable DNS Service Discovery support using Avahi.
+ --disable-ldap disable LDAP support.
--enable-dbus enable DBus CMS code
--disable-largefile omit support for large files
--enable-werror Treat all warnings as errors, useful for
@@ -1558,6 +1566,8 @@ Optional Packages:
--without-tiff Disable tiff support.
--with-avahi-libs Set directory for Avahi library.
--with-avahi-includes Set directory for Avahi includes
+ --with-ldap-libs set directory for LDAP library.
+ --with-ldap-includes set directory for LDAP includes.
--with-browseremoteprotocols=value
Set which protocols to listen for in cups-browsed
(default: dnssd cups)
@@ -1615,6 +1625,10 @@ Some influential environment variables:
linker flags for AVAHI_GLIB, overriding pkg-config
GIO_CFLAGS C compiler flags for GIO, overriding pkg-config
GIO_LIBS linker flags for GIO, overriding pkg-config
+ GIO_UNIX_CFLAGS
+ C compiler flags for GIO_UNIX, overriding pkg-config
+ GIO_UNIX_LIBS
+ linker flags for GIO_UNIX, overriding pkg-config
LCMS_CFLAGS C compiler flags for LCMS, overriding pkg-config
LCMS_LIBS linker flags for LCMS, overriding pkg-config
FREETYPE_CFLAGS
@@ -1706,7 +1720,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-cups-filters configure 1.0.71
+cups-filters configure 1.0.73
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2256,6 +2270,37 @@ fi
} # ac_fn_cxx_check_header_mongrel
+# ac_fn_cxx_check_header_compile LINENO HEADER VAR INCLUDES
+# ---------------------------------------------------------
+# Tests whether HEADER exists and can be compiled using the include files in
+# INCLUDES, setting the cache variable VAR accordingly.
+ac_fn_cxx_check_header_compile ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+#include <$2>
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ eval "$3=yes"
+else
+ eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_cxx_check_header_compile
+
# ac_fn_cxx_check_type LINENO TYPE VAR INCLUDES
# ---------------------------------------------
# Tests whether TYPE exists after having included INCLUDES, setting cache
@@ -2313,7 +2358,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
-It was created by cups-filters $as_me 1.0.71, which was
+It was created by cups-filters $as_me 1.0.73, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@@ -3264,7 +3309,7 @@ fi
# Define the identity of the package.
PACKAGE='cups-filters'
- VERSION='1.0.71'
+ VERSION='1.0.73'
cat >>confdefs.h <<_ACEOF
@@ -16755,6 +16800,294 @@ fi
+# Check whether --enable-ldap was given.
+if test "${enable_ldap+set}" = set; then :
+ enableval=$enable_ldap; enable_ldap="$enableval"
+else
+ enable_ldap=yes
+
+fi
+
+
+# Check whether --with-ldap-libs was given.
+if test "${with_ldap_libs+set}" = set; then :
+ withval=$with_ldap_libs; LDFLAGS="-L$withval $LDFLAGS"
+ DSOFLAGS="-L$withval $DSOFLAGS"
+fi
+
+
+# Check whether --with-ldap-includes was given.
+if test "${with_ldap_includes+set}" = set; then :
+ withval=$with_ldap_includes; CFLAGS="-I$withval $CFLAGS"
+ CPPFLAGS="-I$withval $CPPFLAGS"
+fi
+
+
+if test x$enable_ldap != xno; then
+
+ ac_fn_cxx_check_header_mongrel "$LINENO" "ldap.h" "ac_cv_header_ldap_h" "$ac_includes_default"
+if test "x$ac_cv_header_ldap_h" = xyes; then :
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing ldap_initialize" >&5
+$as_echo_n "checking for library containing ldap_initialize... " >&6; }
+if ${ac_cv_search_ldap_initialize+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char ldap_initialize ();
+int
+main ()
+{
+return ldap_initialize ();
+ ;
+ return 0;
+}
+_ACEOF
+for ac_lib in '' ldap; do
+ if test -z "$ac_lib"; then
+ ac_res="none required"
+ else
+ ac_res=-l$ac_lib
+ LIBS="-l$ac_lib $ac_func_search_save_LIBS"
+ fi
+ if ac_fn_cxx_try_link "$LINENO"; then :
+ ac_cv_search_ldap_initialize=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext
+ if ${ac_cv_search_ldap_initialize+:} false; then :
+ break
+fi
+done
+if ${ac_cv_search_ldap_initialize+:} false; then :
+
+else
+ ac_cv_search_ldap_initialize=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_ldap_initialize" >&5
+$as_echo "$ac_cv_search_ldap_initialize" >&6; }
+ac_res=$ac_cv_search_ldap_initialize
+if test "$ac_res" != no; then :
+ test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+
+$as_echo "#define HAVE_LDAP /**/" >>confdefs.h
+
+
+$as_echo "#define HAVE_OPENLDAP /**/" >>confdefs.h
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ldap_start_tls in -lldap" >&5
+$as_echo_n "checking for ldap_start_tls in -lldap... " >&6; }
+if ${ac_cv_lib_ldap_ldap_start_tls+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lldap $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char ldap_start_tls ();
+int
+main ()
+{
+return ldap_start_tls ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_link "$LINENO"; then :
+ ac_cv_lib_ldap_ldap_start_tls=yes
+else
+ ac_cv_lib_ldap_ldap_start_tls=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ldap_ldap_start_tls" >&5
+$as_echo "$ac_cv_lib_ldap_ldap_start_tls" >&6; }
+if test "x$ac_cv_lib_ldap_ldap_start_tls" = xyes; then :
+
+$as_echo "#define HAVE_LDAP_SSL /**/" >>confdefs.h
+
+fi
+
+else
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ldap_init in -lldap" >&5
+$as_echo_n "checking for ldap_init in -lldap... " >&6; }
+if ${ac_cv_lib_ldap_ldap_init+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lldap $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char ldap_init ();
+int
+main ()
+{
+return ldap_init ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_link "$LINENO"; then :
+ ac_cv_lib_ldap_ldap_init=yes
+else
+ ac_cv_lib_ldap_ldap_init=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ldap_ldap_init" >&5
+$as_echo "$ac_cv_lib_ldap_ldap_init" >&6; }
+if test "x$ac_cv_lib_ldap_ldap_init" = xyes; then :
+
+
+$as_echo "#define HAVE_LDAP /**/" >>confdefs.h
+
+
+$as_echo "#define HAVE_MOZILLA_LDAP /**/" >>confdefs.h
+
+ for ac_header in ldap_ssl.h
+do :
+ ac_fn_cxx_check_header_compile "$LINENO" "ldap_ssl.h" "ac_cv_header_ldap_ssl_h" "#include <ldap.h>
+"
+if test "x$ac_cv_header_ldap_ssl_h" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_LDAP_SSL_H 1
+_ACEOF
+
+fi
+
+done
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ldapssl_init in -lldap" >&5
+$as_echo_n "checking for ldapssl_init in -lldap... " >&6; }
+if ${ac_cv_lib_ldap_ldapssl_init+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lldap $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char ldapssl_init ();
+int
+main ()
+{
+return ldapssl_init ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_link "$LINENO"; then :
+ ac_cv_lib_ldap_ldapssl_init=yes
+else
+ ac_cv_lib_ldap_ldapssl_init=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ldap_ldapssl_init" >&5
+$as_echo "$ac_cv_lib_ldap_ldapssl_init" >&6; }
+if test "x$ac_cv_lib_ldap_ldapssl_init" = xyes; then :
+
+$as_echo "#define HAVE_LDAP_SSL /**/" >>confdefs.h
+
+fi
+
+fi
+
+
+fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ldap_set_rebind_proc in -lldap" >&5
+$as_echo_n "checking for ldap_set_rebind_proc in -lldap... " >&6; }
+if ${ac_cv_lib_ldap_ldap_set_rebind_proc+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lldap $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char ldap_set_rebind_proc ();
+int
+main ()
+{
+return ldap_set_rebind_proc ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_link "$LINENO"; then :
+ ac_cv_lib_ldap_ldap_set_rebind_proc=yes
+else
+ ac_cv_lib_ldap_ldap_set_rebind_proc=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ldap_ldap_set_rebind_proc" >&5
+$as_echo "$ac_cv_lib_ldap_ldap_set_rebind_proc" >&6; }
+if test "x$ac_cv_lib_ldap_ldap_set_rebind_proc" = xyes; then :
+
+$as_echo "#define HAVE_LDAP_REBIND_PROC /**/" >>confdefs.h
+
+fi
+
+
+fi
+
+
+
+fi
+
+
+
pkg_failed=no
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GLIB" >&5
$as_echo_n "checking for GLIB... " >&6; }
@@ -17043,6 +17376,104 @@ fi
+GIO_UNIX_CFLAGS=""
+GIO_UNIX_LIBS=""
+if test "x$PKGCONFIG" != x; then
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GIO_UNIX" >&5
+$as_echo_n "checking for GIO_UNIX... " >&6; }
+
+if test -n "$GIO_UNIX_CFLAGS"; then
+ pkg_cv_GIO_UNIX_CFLAGS="$GIO_UNIX_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gio-unix-2.0\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "gio-unix-2.0") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_GIO_UNIX_CFLAGS=`$PKG_CONFIG --cflags "gio-unix-2.0" 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes
+else
+ pkg_failed=yes
+fi
+ else
+ pkg_failed=untried
+fi
+if test -n "$GIO_UNIX_LIBS"; then
+ pkg_cv_GIO_UNIX_LIBS="$GIO_UNIX_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gio-unix-2.0\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "gio-unix-2.0") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_GIO_UNIX_LIBS=`$PKG_CONFIG --libs "gio-unix-2.0" 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes
+else
+ pkg_failed=yes
+fi
+ else
+ pkg_failed=untried
+fi
+
+
+
+if test $pkg_failed = yes; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+ _pkg_short_errors_supported=yes
+else
+ _pkg_short_errors_supported=no
+fi
+ if test $_pkg_short_errors_supported = yes; then
+ GIO_UNIX_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "gio-unix-2.0" 2>&1`
+ else
+ GIO_UNIX_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "gio-unix-2.0" 2>&1`
+ fi
+ # Put the nasty error message in config.log where it belongs
+ echo "$GIO_UNIX_PKG_ERRORS" >&5
+
+ as_fn_error $? "Package requirements (gio-unix-2.0) were not met:
+
+$GIO_UNIX_PKG_ERRORS
+
+Consider adjusting the PKG_CONFIG_PATH environment variable if you
+installed software in a non-standard prefix.
+
+Alternatively, you may set the environment variables GIO_UNIX_CFLAGS
+and GIO_UNIX_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details." "$LINENO" 5
+elif test $pkg_failed = untried; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it
+is in your PATH or set the PKG_CONFIG environment variable to the full
+path to pkg-config.
+
+Alternatively, you may set the environment variables GIO_UNIX_CFLAGS
+and GIO_UNIX_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details.
+
+To get pkg-config, see <http://pkg-config.freedesktop.org/>.
+See \`config.log' for more details" "$LINENO" 5; }
+else
+ GIO_UNIX_CFLAGS=$pkg_cv_GIO_UNIX_CFLAGS
+ GIO_UNIX_LIBS=$pkg_cv_GIO_UNIX_LIBS
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+fi
+fi
+
+
+
# Check whether --with-browseremoteprotocols was given.
if test "${with_browseremoteprotocols+set}" = set; then :
@@ -19459,7 +19890,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
-This file was extended by cups-filters $as_me 1.0.71, which was
+This file was extended by cups-filters $as_me 1.0.73, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -19525,7 +19956,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
-cups-filters config.status 1.0.71
+cups-filters config.status 1.0.73
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
diff --git a/configure.ac b/configure.ac
index 0fe292b91..e2a5e2718 100644
--- a/configure.ac
+++ b/configure.ac
@@ -7,7 +7,7 @@ AC_PREREQ([2.65])
# ====================
m4_define([cups_filters_version_major],[1])
m4_define([cups_filters_version_minor],[0])
-m4_define([cups_filters_version_micro],[71])
+m4_define([cups_filters_version_micro],[73])
m4_define([cups_filters_version],[cups_filters_version_major.cups_filters_version_minor.cups_filters_version_micro])
# =============
@@ -287,6 +287,57 @@ fi
AC_SUBST(AVAHI_LIBS)
AC_SUBST(AVAHI_CFLAGS)
+dnl
+dnl "$Id: cups-ldap.m4 9771 2011-05-12 05:21:56Z mike $"
+dnl
+dnl LDAP configuration stuff for CUPS.
+dnl
+dnl Copyright 2007-2011 by Apple Inc.
+dnl Copyright 2003-2006 by Easy Software Products, all rights reserved.
+dnl
+dnl These coded instructions, statements, and computer programs are the
+dnl property of Apple Inc. and are protected by Federal copyright
+dnl law. Distribution and use rights are outlined in the file "LICENSE.txt"
+dnl which should have been included with this file. If this file is
+dnl file is missing or damaged, see the license at "http://www.cups.org/".
+dnl
+
+AC_ARG_ENABLE([ldap], [AS_HELP_STRING([--disable-ldap], [disable LDAP support.])],
+ [enable_ldap="$enableval"],
+ [enable_ldap=yes]
+)
+AC_ARG_WITH([ldap-libs], [AS_HELP_STRING([--with-ldap-libs], [set directory for LDAP library.])],
+ LDFLAGS="-L$withval $LDFLAGS"
+ DSOFLAGS="-L$withval $DSOFLAGS",)
+AC_ARG_WITH([ldap-includes], [AS_HELP_STRING([--with-ldap-includes], [set directory for LDAP includes.])],
+ CFLAGS="-I$withval $CFLAGS"
+ CPPFLAGS="-I$withval $CPPFLAGS",)
+
+if test x$enable_ldap != xno; then
+
+ AC_CHECK_HEADER([ldap.h], [
+ AC_SEARCH_LIBS([ldap_initialize], [ldap], [
+ AC_DEFINE([HAVE_LDAP], [], [Define if LDAP support should be enabled])
+ AC_DEFINE([HAVE_OPENLDAP], [], [If LDAP support is that of OpenLDAP])
+ AC_CHECK_LIB([ldap], [ldap_start_tls],
+ AC_DEFINE([HAVE_LDAP_SSL], [], [If LDAP has SSL/TLS support enabled]))],[
+
+ AC_CHECK_LIB([ldap], [ldap_init], [
+ AC_DEFINE([HAVE_LDAP], [], [Define if LDAP support should be enabled])
+ AC_DEFINE([HAVE_MOZILLA_LDAP], [], [If LDAP support is that of Mozilla])
+ AC_CHECK_HEADERS([ldap_ssl.h], [], [], [#include <ldap.h>])
+ AC_CHECK_LIB([ldap], [ldapssl_init],
+ AC_DEFINE([HAVE_LDAP_SSL], [], [If LDAP has SSL/TLS support enabled]))])]
+ )
+ AC_CHECK_LIB([ldap], [ldap_set_rebind_proc], AC_DEFINE([HAVE_LDAP_REBIND_PROC], [], [If libldap implements ldap_set_rebind_proc]))
+ ])
+
+fi
+
+dnl
+dnl End of "$Id: cups-ldap.m4 9771 2011-05-12 05:21:56Z mike $".
+dnl
+
PKG_CHECK_MODULES(GLIB, [glib-2.0 >= 2.30.2])
AC_SUBST(GLIB_CFLAGS)
AC_SUBST(GLIB_LIBS)
@@ -306,6 +357,14 @@ fi
AC_SUBST(GIO_CFLAGS)
AC_SUBST(GIO_LIBS)
+GIO_UNIX_CFLAGS=""
+GIO_UNIX_LIBS=""
+if test "x$PKGCONFIG" != x; then
+ PKG_CHECK_MODULES(GIO_UNIX, [gio-unix-2.0])
+fi
+AC_SUBST(GIO_UNIX_CFLAGS)
+AC_SUBST(GIO_UNIX_LIBS)
+
AC_ARG_WITH([browseremoteprotocols],
[AS_HELP_STRING([--with-browseremoteprotocols=value], [Set which protocols to listen for in cups-browsed (default: dnssd cups)])],
[with_browseremoteprotocols="$withval"],
diff --git a/cupsfilters/attr.c b/cupsfilters/attr.c
index bce077fc6..11c87d247 100644
--- a/cupsfilters/attr.c
+++ b/cupsfilters/attr.c
@@ -22,8 +22,8 @@
* Include necessary headers.
*/
-#include "driver.h"
#include <config.h>
+#include "driver.h"
#include <string.h>
#include <ctype.h>
diff --git a/cupsfilters/cmyk.c b/cupsfilters/cmyk.c
index e75eed729..b5329eafe 100644
--- a/cupsfilters/cmyk.c
+++ b/cupsfilters/cmyk.c
@@ -33,8 +33,8 @@
* Include necessary headers.
*/
-#include "driver.h"
#include <config.h>
+#include "driver.h"
#include <string.h>
#include <ctype.h>
diff --git a/cupsfilters/dither.c b/cupsfilters/dither.c
index dfefed7c1..082065717 100644
--- a/cupsfilters/dither.c
+++ b/cupsfilters/dither.c
@@ -23,8 +23,8 @@
* Include necessary headers.
*/
-#include "driver.h"
#include <config.h>
+#include "driver.h"
/*
diff --git a/cupsfilters/image-private.h b/cupsfilters/image-private.h
index c0667ac65..d441c4f69 100644
--- a/cupsfilters/image-private.h
+++ b/cupsfilters/image-private.h
@@ -22,9 +22,9 @@
* Include necessary headers...
*/
+# include <config.h>
# include "image.h"
# include <cups/cups.h>
-# include <config.h>
# define DEBUG_printf(x)
# define DEBUG_puts(x)
# include <stdlib.h>
diff --git a/cupsfilters/raster.c b/cupsfilters/raster.c
index 1465bf71b..847c66ccd 100644
--- a/cupsfilters/raster.c
+++ b/cupsfilters/raster.c
@@ -12,6 +12,7 @@
* and apply them to the CUPS Raster header.
*/
+#include <config.h>
#include <cups/cups.h>
#if (CUPS_VERSION_MAJOR > 1) || (CUPS_VERSION_MINOR > 6)
#define HAVE_CUPS_1_7 1
@@ -22,7 +23,6 @@
*/
#include "driver.h"
-#include <config.h>
#include <string.h>
#include <ctype.h>
#ifdef HAVE_CUPS_1_7
diff --git a/filter/banner.c b/filter/banner.c
index 006179e4e..a8230b73a 100644
--- a/filter/banner.c
+++ b/filter/banner.c
@@ -127,7 +127,7 @@ banner_t * banner_new_from_file(const char *filename,
{
FILE *f;
char *line = NULL;
- ssize_t len = 0;
+ size_t len = 0;
int linenr = 0;
banner_t *banner = NULL;
diff --git a/filter/banner.h b/filter/banner.h
index 95e75ea8d..951baefa9 100644
--- a/filter/banner.h
+++ b/filter/banner.h
@@ -17,8 +17,8 @@
#ifndef banner_h
#define banner_h
-#include <stdio.h>
#include <config.h>
+#include <stdio.h>
#include <cups/cups.h>
enum banner_info {
diff --git a/filter/bannertopdf.c b/filter/bannertopdf.c
index 0bde2c1a0..b78ea377a 100644
--- a/filter/bannertopdf.c
+++ b/filter/bannertopdf.c
@@ -15,6 +15,7 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <config.h>
#include <stdio.h>
#include <stdarg.h>
#include <math.h>
diff --git a/filter/foomatic-rip/foomaticrip.c b/filter/foomatic-rip/foomaticrip.c
index 90a851c18..1461c24f0 100644
--- a/filter/foomatic-rip/foomaticrip.c
+++ b/filter/foomatic-rip/foomaticrip.c
@@ -358,6 +358,8 @@ void process_cmdline_options()
drivers do that. We may have to standardize the verbose
names to make them work as selections, too. */
+ if (value[0] == '\0')
+ continue;
p = strtok(value, ",");
do {
if ((opt = find_option("PageSize")) && option_accepts_value(opt, p))
diff --git a/filter/foomatic-rip/postscript.c b/filter/foomatic-rip/postscript.c
index 59c33197b..d0d5d2a0d 100644
--- a/filter/foomatic-rip/postscript.c
+++ b/filter/foomatic-rip/postscript.c
@@ -702,7 +702,7 @@ void _print_ps(stream_t *stream)
if (spooler == SPOOLER_CUPS &&
linetype == LT_BEGIN_FEATURE &&
!option_get_value(o, optionset("notfirst")) &&
- strcmp(option_get_value(o, optset) ?: "", value) != 0 &&
+ strcmp((val = option_get_value(o, optset)) ? val : "", value) != 0 &&
(inheader || option_get_section(o) == SECTION_PAGESETUP)) {
/* We have the first occurence of an option
diff --git a/filter/foomatic-rip/process.c b/filter/foomatic-rip/process.c
index 3b9e71854..8badf777c 100644
--- a/filter/foomatic-rip/process.c
+++ b/filter/foomatic-rip/process.c
@@ -28,6 +28,7 @@
#include <sys/wait.h>
#include <errno.h>
#include <stdlib.h>
+#include <signal.h>
int kidgeneration = 0;
diff --git a/filter/foomatic-rip/renderer.c b/filter/foomatic-rip/renderer.c
index f3ab878f0..c5582cdb1 100644
--- a/filter/foomatic-rip/renderer.c
+++ b/filter/foomatic-rip/renderer.c
@@ -20,7 +20,7 @@
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
-
+#include <config.h>
#include <signal.h>
#include <ctype.h>
#include <stdlib.h>
diff --git a/filter/gstoraster.c b/filter/gstoraster.c
index 859070dcb..2750626e9 100644
--- a/filter/gstoraster.c
+++ b/filter/gstoraster.c
@@ -30,12 +30,12 @@ MIT Open Source License - http://www.opensource.org/
/* PS/PDF to CUPS Raster filter based on Ghostscript */
+#include <config.h>
#include <cups/cups.h>
#if (CUPS_VERSION_MAJOR > 1) || (CUPS_VERSION_MINOR > 6)
#define HAVE_CUPS_1_7 1
#endif
-#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
diff --git a/filter/pdf.cxx b/filter/pdf.cxx
index d04231ae6..837f73150 100644
--- a/filter/pdf.cxx
+++ b/filter/pdf.cxx
@@ -15,6 +15,7 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <config.h>
#include "pdf.h"
#include <PDFDoc.h>
@@ -24,7 +25,6 @@
#include <GfxFont.h>
#include <Page.h>
#include <PDFDocEncoding.h>
-#include <config.h>
#ifdef HAVE_CPP_POPPLER_VERSION_H
#include "cpp/poppler-version.h"
#endif
diff --git a/filter/pdftoijs.cxx b/filter/pdftoijs.cxx
index 52d4a715a..22bc33f43 100644
--- a/filter/pdftoijs.cxx
+++ b/filter/pdftoijs.cxx
@@ -511,8 +511,13 @@ err1:
}
/* replace memory allocation methods for memory check */
+/* For compatibility with g++ >= 4.7 compilers _GLIBCXX_THROW
+ * should be used as a guard, otherwise use traditional definition */
+#ifndef _GLIBCXX_THROW
+#define _GLIBCXX_THROW throw
+#endif
-void * operator new(size_t size) throw (std::bad_alloc)
+void * operator new(size_t size) _GLIBCXX_THROW (std::bad_alloc)
{
return gmalloc(size);
}
@@ -522,7 +527,7 @@ void operator delete(void *p) throw ()
gfree(p);
}
-void * operator new[](size_t size) throw (std::bad_alloc)
+void * operator new[](size_t size) _GLIBCXX_THROW (std::bad_alloc)
{
return gmalloc(size);
}
diff --git a/filter/pdftoopvp/OPVPOutputDev.cxx b/filter/pdftoopvp/OPVPOutputDev.cxx
index 8a205845e..7101560f3 100644
--- a/filter/pdftoopvp/OPVPOutputDev.cxx
+++ b/filter/pdftoopvp/OPVPOutputDev.cxx
@@ -1811,10 +1811,14 @@ void OPVPOutputDev::drawSoftMaskedImage(GfxState *state, Object *ref,
#if POPPLER_VERSION_MAJOR <= 0 && (POPPLER_VERSION_MINOR <= 20 || (POPPLER_VERSION_MINOR == 21 && POPPLER_VERSION_MICRO <= 2))
maskSplash->drawImage(&imageSrc, &imgMaskData,
splashModeMono8, gFalse, maskWidth, maskHeight, mat);
-#else
+#elif POPPLER_VERSION_MAJOR <= 0 && POPPLER_VERSION_MINOR <= 33
maskSplash->drawImage(&imageSrc, &imgMaskData,
splashModeMono8, gFalse, maskWidth, maskHeight,
mat,gFalse);
+#else
+ maskSplash->drawImage(&imageSrc, 0, &imgMaskData,
+ splashModeMono8, gFalse, maskWidth, maskHeight,
+ mat,gFalse);
#endif
delete imgMaskData.imgStr;
maskStr->close();
diff --git a/filter/pdftoopvp/oprs/OPRS.cxx b/filter/pdftoopvp/oprs/OPRS.cxx
index 15710c110..f22fdff37 100644
--- a/filter/pdftoopvp/oprs/OPRS.cxx
+++ b/filter/pdftoopvp/oprs/OPRS.cxx
@@ -240,8 +240,10 @@ SplashError OPRS::drawImage(SplashImageSource src, void *srcData,
if (rasterMode) {
#if POPPLER_VERSION_MAJOR <= 0 && (POPPLER_VERSION_MINOR <= 20 || (POPPLER_VERSION_MINOR == 21 && POPPLER_VERSION_MICRO <= 2))
return splash->drawImage(src,srcData,srcMode,srcAlpha,w,h,mat);
-#else
+#elif POPPLER_VERSION_MAJOR <= 0 && POPPLER_VERSION_MINOR <= 33
return splash->drawImage(src,srcData,srcMode,srcAlpha,w,h,mat,gFalse);
+#else
+ return splash->drawImage(src,0,srcData,srcMode,srcAlpha,w,h,mat,gFalse);
#endif
} else {
return opvpSplash->drawImage(src,srcData,srcMode,srcAlpha,w,h,mat);
diff --git a/filter/pdftoopvp/pdftoopvp.cxx b/filter/pdftoopvp/pdftoopvp.cxx
index 3b5d44f5b..e1eef8a61 100644
--- a/filter/pdftoopvp/pdftoopvp.cxx
+++ b/filter/pdftoopvp/pdftoopvp.cxx
@@ -770,7 +770,13 @@ err2:
}
/* for memory debug */
-void *operator new(size_t size) throw (std::bad_alloc)
+/* For compatibility with g++ >= 4.7 compilers _GLIBCXX_THROW
+ * should be used as a guard, otherwise use traditional definition */
+#ifndef _GLIBCXX_THROW
+#define _GLIBCXX_THROW throw
+#endif
+
+void * operator new(size_t size) _GLIBCXX_THROW (std::bad_alloc)
{
void *p = malloc(size);
return p;
diff --git a/filter/pdftops.c b/filter/pdftops.c
index aa27c7ba8..5cef9748c 100644
--- a/filter/pdftops.c
+++ b/filter/pdftops.c
@@ -26,6 +26,7 @@
* Include necessary headers...
*/
+#include <config.h>
#include <cups/cups.h>
#include <cups/ppd.h>
#include <cups/file.h>
@@ -35,7 +36,6 @@
#include <errno.h>
#include <string.h>
#include <ctype.h>
-#include <config.h>
#include <cupsfilters/image-private.h>
#define MAX_CHECK_COMMENT_LINES 20
diff --git a/filter/pdftoraster.cxx b/filter/pdftoraster.cxx
index d78573f93..926d78671 100644
--- a/filter/pdftoraster.cxx
+++ b/filter/pdftoraster.cxx
@@ -26,6 +26,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
pdf to raster filter
*/
+#include <config.h>
#include <cups/cups.h>
#if (CUPS_VERSION_MAJOR > 1) || (CUPS_VERSION_MINOR > 6)
#define HAVE_CUPS_1_7 1
@@ -33,7 +34,6 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#define USE_CMS
-#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#ifdef HAVE_CPP_POPPLER_VERSION_H
@@ -2146,8 +2146,13 @@ err1:
}
/* replace memory allocation methods for memory check */
+/* For compatibility with g++ >= 4.7 compilers _GLIBCXX_THROW
+ * should be used as a guard, otherwise use traditional definition */
+#ifndef _GLIBCXX_THROW
+#define _GLIBCXX_THROW throw
+#endif
-void * operator new(size_t size) throw (std::bad_alloc)
+void * operator new(size_t size) _GLIBCXX_THROW (std::bad_alloc)
{
return gmalloc(size);
}
@@ -2157,7 +2162,7 @@ void operator delete(void *p) throw ()
gfree(p);
}
-void * operator new[](size_t size) throw (std::bad_alloc)
+void * operator new[](size_t size) _GLIBCXX_THROW (std::bad_alloc)
{
return gmalloc(size);
}
diff --git a/filter/pdfutils.c b/filter/pdfutils.c
index 99f370751..5a625117a 100644
--- a/filter/pdfutils.c
+++ b/filter/pdfutils.c
@@ -13,6 +13,7 @@
#include <stdarg.h>
#include <memory.h>
#include <stdlib.h>
+#include <string.h>
#include "pdfutils.h"
#include "fontembed/embed.h"
diff --git a/filter/rastertoescpx.c b/filter/rastertoescpx.c
index 79eb88c24..384300ddd 100644
--- a/filter/rastertoescpx.c
+++ b/filter/rastertoescpx.c
@@ -923,7 +923,7 @@ StartPage(ppd_file_t *ppd, /* I - PPD file */
fputs("DEBUG: Pointer list at start of page...\n", stderr);
for (band = DotAvailList; band != NULL; band = band->next)
- fprintf(stderr, "DEBUG: %p\n", band);
+ fprintf(stderr, "DEBUG: %p\n", (void*)band);
fputs("DEBUG: ----END----\n", stderr);
@@ -996,7 +996,7 @@ StartPage(ppd_file_t *ppd, /* I - PPD file */
band->count = DotRowCount;
fprintf(stderr, "DEBUG: DotBands[%d][%d] = %p, x = %d, y = %d, plane = %d, count = %d\n",
- subrow, plane, band, band->x, band->y, band->plane, band->count);
+ subrow, plane, (void*)band, band->x, band->y, band->plane, band->count);
}
subrow = (subrow + DotRowFeed) % modrow;
@@ -1109,9 +1109,9 @@ EndPage(ppd_file_t *ppd, /* I - PPD file */
fputs("DEBUG: Pointer list at end of page...\n", stderr);
for (band = DotUsedList; band != NULL; band = band->next)
- fprintf(stderr, "DEBUG: %p (used)\n", band);
+ fprintf(stderr, "DEBUG: %p (used)\n", (void*)band);
for (band = DotAvailList; band != NULL; band = band->next)
- fprintf(stderr, "DEBUG: %p (avail)\n", band);
+ fprintf(stderr, "DEBUG: %p (avail)\n", (void*)band);
fputs("DEBUG: ----END----\n", stderr);
@@ -1122,7 +1122,7 @@ EndPage(ppd_file_t *ppd, /* I - PPD file */
OutputBand(ppd, header, band);
fprintf(stderr, "DEBUG: freeing used band %p, prev = %p, next = %p\n",
- band, band->prev, band->next);
+ (void*)band, (void*)band->prev, (void*)band->next);
free(band->buffer);
free(band);
@@ -1137,7 +1137,7 @@ EndPage(ppd_file_t *ppd, /* I - PPD file */
next = band->next;
fprintf(stderr, "DEBUG: freeing avail band %p, prev = %p, next = %p\n",
- band, band->prev, band->next);
+ (void*)band, (void*)band->prev, (void*)band->next);
free(band->buffer);
free(band);
@@ -1506,7 +1506,7 @@ OutputBand(ppd_file_t *ppd, /* I - PPD file */
DotRowCurrent = band->y;
fprintf(stderr, "DEBUG: Printing band %p, x = %d, y = %d, plane = %d, count = %d, OutputFeed = %d\n",
- band, band->x, band->y, band->plane, band->count, OutputFeed);
+ (void*)band, band->x, band->y, band->plane, band->count, OutputFeed);
/*
* Compute step values...
@@ -1722,7 +1722,7 @@ ProcessLine(ppd_file_t *ppd, /* I - PPD file */
*/
fprintf(stderr, "DEBUG: Blank band %p, x = %d, y = %d, plane = %d, count = %d\n",
- band, band->x, band->y, band->plane, band->count);
+ (void*)band, band->x, band->y, band->plane, band->count);
band->y += band->count * DotRowStep;
band->row = 0;
diff --git a/filter/sys5ippprinter.c b/filter/sys5ippprinter.c
index a7785a3a0..39920277c 100644
--- a/filter/sys5ippprinter.c
+++ b/filter/sys5ippprinter.c
@@ -26,6 +26,7 @@
* Include necessary headers...
*/
+#include <config.h>
#include <cups/cups.h>
#include <cups/ppd.h>
#include <cups/file.h>
@@ -37,7 +38,6 @@
#include <errno.h>
#include <string.h>
#include <ctype.h>
-#include <config.h>
#include <cupsfilters/image-private.h>
#define MAX_CHECK_COMMENT_LINES 20
diff --git a/filter/urftopdf.cpp b/filter/urftopdf.cpp
index 51aff3f4b..ec3f8dce3 100644
--- a/filter/urftopdf.cpp
+++ b/filter/urftopdf.cpp
@@ -27,6 +27,7 @@
#include <stdlib.h>
#include <string.h>
#include <limits>
+#include <errno.h>
#include <arpa/inet.h> // ntohl
@@ -54,7 +55,7 @@
void die(const char * str)
{
- fprintf(stderr, "CRIT: (" PROGRAM ") die(%s) [%m]\n", str);
+ fprintf(stderr, "CRIT: (" PROGRAM ") die(%s) [%s]\n", str, strerror(errno));
exit(1);
}
diff --git a/fontembed/embed_pdf.h b/fontembed/embed_pdf.h
index 49bc8ace4..d837e4aeb 100644
--- a/fontembed/embed_pdf.h
+++ b/fontembed/embed_pdf.h
@@ -22,7 +22,7 @@ typedef struct {
char *registry,*ordering;
int supplement;
- char data[]; // used for storing e.g. >fontname
+ char data[1]; // used for storing e.g. >fontname
} EMB_PDF_FONTDESCR;
typedef struct {
@@ -34,7 +34,7 @@ typedef struct {
int default_width;
int *warray; // format: (len c w ... w)* if (len<0) { c1 (c2=c1+(-len)) w } else { c w[len] }, terminated by len==0
- int data[];
+ int data[1];
} EMB_PDF_FONTWIDTHS;
const char *emb_pdf_get_font_subtype(EMB_PARAMS *emb);
diff --git a/fontembed/main.c b/fontembed/main.c
index 4433703f5..af7700417 100644
--- a/fontembed/main.c
+++ b/fontembed/main.c
@@ -1,10 +1,11 @@
+#include "config.h"
#include "sfnt.h"
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
+#include <errno.h>
#include "embed.h"
-#include "config.h"
#if 0
enum { TTF_OTF, TYPE1 } inputFile;
@@ -89,7 +90,7 @@ void example_write_fontdescr(OTF_FILE *otf,const char *outfile) // {{{
if (outfile) {
FILE *f=fopen(outfile,"w");
if (!f) {
- fprintf(stderr,"Opening \"%s\" for writing failed: %m\n",outfile);
+ fprintf(stderr,"Opening \"%s\" for writing failed: %s\n",outfile, strerror(errno));
assert(0);
emb_close(emb);
return;
diff --git a/utils/cups-browsed.8 b/utils/cups-browsed.8
index a384898c5..b6db9423c 100644
--- a/utils/cups-browsed.8
+++ b/utils/cups-browsed.8
@@ -14,7 +14,7 @@
.fam T
.fi
.SH DESCRIPTION
-\fBcups-browsed\fP has three independently switchable functions:
+\fBcups-browsed\fP has four independently switchable functions:
.IP 1. 4
Browse Bonjour broadcasts of remote printers and create/remove local
raw queues pointing to these printers.
@@ -22,9 +22,12 @@ raw queues pointing to these printers.
Browse CUPS broadcasts of remote printers and create/remove local raw
queues pointing to these printers.
.IP 3. 4
+Browse an LDAP server for printers and create/remove local raw
+queues pointing to these printers.
+.IP 4. 4
Broadcast local queues with the CUPS protocol.
.PP
-Note that 2. and 3. are only to allow communication with legacy CUPS servers (1.5.x or older) on the remote machine(s). The standard method to broadcast for shared/network printers to broadcast their presence is Bonjour. The CUPS broadcasting/browsing protocol is deprecated.
+Note that 2. and 4. are only to allow communication with legacy CUPS servers (1.5.x or older) on the remote machine(s). The standard method to broadcast for shared/network printers to broadcast their presence is Bonjour. The CUPS broadcasting/browsing protocol is deprecated.
cups-browsed can be run permanently (from system boot to shutdown) or on-demand (for example to save resources on mobile devices). For running it on-demend an auto-shutdown feature can be activated to let cups-browsed terminate when it does not have queues any more to take care of.
@@ -59,7 +62,12 @@ In environments with only cups 1.6.x servers and clients (plus
enables the automatic discovery of remote queues and their display in
printing dialogues of applications and with command line tools.
.PP
-The facility provided by 3. means that servers running cups 1.6.x plus
+The facility provided by 3. allows printers that are registered in an LDAP
+server to be added as local queues. CUPS servers 1.5.x are able to automatically
+register printers in LDAP. The facility provided by \fBcups-browsed\fP allows
+a filter string to further limit the printers that are browsed from LDAP.
+.PP
+The facility provided by 4. means that servers running cups 1.6.x plus
\fBcups-browsed\fP can broadcast their local queues so that clients with cups
1.5.x get these queues automatically available. The outcome of 2. is
that clients running cups 1.6.x plus \fBcups-browsed\fP can use the CUPS
diff --git a/utils/cups-browsed.c b/utils/cups-browsed.c
index 19d15edd6..3c76a5b94 100644
--- a/utils/cups-browsed.c
+++ b/utils/cups-browsed.c
@@ -51,9 +51,77 @@
#include <gio/gio.h>
+
+#ifdef HAVE_LDAP
+# ifdef __sun
+# include <lber.h>
+# endif /* __sun */
+# include <ldap.h>
+# ifdef HAVE_LDAP_SSL_H
+# include <ldap_ssl.h>
+# endif /* HAVE_LDAP_SSL_H */
+#endif /* HAVE_LDAP */
+
+
+#ifdef HAVE_LDAP
+LDAP *BrowseLDAPHandle = NULL;
+ /* Handle to LDAP server */
+char *BrowseLDAPBindDN = NULL,
+ /* LDAP login DN */
+ *BrowseLDAPDN = NULL,
+ /* LDAP search DN */
+ *BrowseLDAPPassword = NULL,
+ /* LDAP login password */
+ *BrowseLDAPServer = NULL,
+ /* LDAP server to use */
+ *BrowseLDAPFilter = NULL;
+ /* LDAP query filter */
+int BrowseLDAPUpdate = TRUE,
+ /* enables LDAP updates */
+ BrowseLDAPInitialised = FALSE;
+ /* the init stuff has been done */
+# ifdef HAVE_LDAP_SSL
+char *BrowseLDAPCACertFile = NULL;
+ /* LDAP CA CERT file to use */
+# endif /* HAVE_LDAP_SSL */
+#endif /* HAVE_LDAP */
+
+
+#ifdef HAVE_LDAP
+#define LDAP_BROWSE_FILTER "(objectclass=cupsPrinter)"
+static LDAP *ldap_connect(void);
+static LDAP *ldap_reconnect(void);
+static void ldap_disconnect(LDAP *ld);
+static int ldap_search_rec(LDAP *ld, char *base, int scope,
+ char *filter, char *attrs[],
+ int attrsonly, LDAPMessage **res);
+static int ldap_getval_firststring(LDAP *ld, LDAPMessage *entry,
+ char *attr, char *retval,
+ unsigned long maxsize);
+static void ldap_freeres(LDAPMessage *entry);
+# ifdef HAVE_LDAP_REBIND_PROC
+# if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
+static int ldap_rebind_proc(LDAP *RebindLDAPHandle,
+ LDAP_CONST char *refsp,
+ ber_tag_t request,
+ ber_int_t msgid,
+ void *params);
+# else
+static int ldap_rebind_proc(LDAP *RebindLDAPHandle,
+ char **dnp,
+ char **passwdp,
+ int *authmethodp,
+ int freeit,
+ void *arg);
+# endif /* defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000) */
+# endif /* HAVE_LDAP_REBIND_PROC */
+#endif /* HAVE_LDAP */
+
#include <cups/cups.h>
#include <cups/ppd.h>
+#include "cups-notifier.h"
+
/* Attribute to mark a CUPS queue as created by us */
#define CUPS_BROWSED_MARK "cups-browsed"
@@ -64,6 +132,15 @@
#define TIMEOUT_REMOVE -1
#define TIMEOUT_CHECK_LIST 2
+#define NOTIFY_LEASE_DURATION (24 * 60 * 60)
+#define CUPS_DBUS_NAME "org.cups.cupsd.Notifier"
+#define CUPS_DBUS_PATH "/org/cups/cupsd/Notifier"
+#define CUPS_DBUS_INTERFACE "org.cups.cupsd.Notifier"
+
+#define LOCAL_DEFAULT_PRINTER_FILE "/var/cache/cups/cups-browsed-local-default-printer"
+#define REMOTE_DEFAULT_PRINTER_FILE "/var/cache/cups/cups-browsed-remote-default-printer"
+#define IMPLICIT_CLASS_DEST_HOST_FILE "/var/cache/cups/cups-browsed-dest-host-%s"
+
/* Status of remote printer */
typedef enum printer_status_e {
STATUS_UNCONFIRMED = 0, /* Generated in a previous session */
@@ -84,7 +161,8 @@ typedef struct remote_printer_s {
cups_option_t *options;
printer_status_t status;
time_t timeout;
- int duplicate;
+ void *duplicate_of;
+ int num_duplicates;
char *host;
char *service_name;
char *type;
@@ -173,11 +251,23 @@ static AvahiGLibPoll *glib_poll = NULL;
static AvahiClient *client = NULL;
static AvahiServiceBrowser *sb1 = NULL, *sb2 = NULL;
#endif /* HAVE_AVAHI */
+#ifdef HAVE_LDAP
+static const char * const ldap_attrs[] =/* CUPS LDAP attributes */
+ {
+ "printerDescription",
+ "printerLocation",
+ "printerMakeAndModel",
+ "printerType",
+ "printerURI",
+ NULL
+ };
+#endif /* HAVE_LDAP */
static guint queues_timer_id = 0;
static int browsesocket = -1;
#define BROWSE_DNSSD (1<<0)
#define BROWSE_CUPS (1<<1)
+#define BROWSE_LDAP (1<<2)
static unsigned int BrowseLocalProtocols = 0;
static unsigned int BrowseRemoteProtocols = BROWSE_DNSSD;
static unsigned int BrowseInterval = 60;
@@ -193,6 +283,7 @@ static int autoshutdown = 0;
static int autoshutdown_avahi = 0;
static int autoshutdown_timeout = 30;
static guint autoshutdown_exec_id = 0;
+static const char *default_printer = NULL;
static int debug = 0;
@@ -201,6 +292,10 @@ static void browse_poll_create_subscription (browsepoll_t *context,
http_t *conn);
static gboolean browse_poll_get_notifications (browsepoll_t *context,
http_t *conn);
+static remote_printer_t *generate_local_queue(const char *host, uint16_t port,
+ char *resource, const char *name,
+ const char *type,
+ const char *domain, void *txt);
#if (CUPS_VERSION_MAJOR > 1) || (CUPS_VERSION_MINOR > 5)
#define HAVE_CUPS_1_6 1
@@ -711,6 +806,1289 @@ color_space_score(const char *color_space)
return score;
}
+
+#ifdef HAVE_LDAP_REBIND_PROC
+# if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
+/*
+ * 'ldap_rebind_proc()' - Callback function for LDAP rebind
+ */
+
+static int /* O - Result code */
+ldap_rebind_proc(
+ LDAP *RebindLDAPHandle, /* I - LDAP handle */
+ LDAP_CONST char *refsp, /* I - ??? */
+ ber_tag_t request, /* I - ??? */
+ ber_int_t msgid, /* I - ??? */
+ void *params) /* I - ??? */
+{
+ int rc; /* Result code */
+# if LDAP_API_VERSION > 3000
+ struct berval bval; /* Bind value */
+# endif /* LDAP_API_VERSION > 3000 */
+
+
+ (void)request;
+ (void)msgid;
+ (void)params;
+
+ /*
+ * Bind to new LDAP server...
+ */
+
+ debug_printf("cups-browsed: ldap_rebind_proc: Rebind to %s\n", refsp);
+
+# if LDAP_API_VERSION > 3000
+ bval.bv_val = BrowseLDAPPassword;
+ bval.bv_len = (BrowseLDAPPassword == NULL) ? 0 : strlen(BrowseLDAPPassword);
+
+ rc = ldap_sasl_bind_s(RebindLDAPHandle, BrowseLDAPBindDN, LDAP_SASL_SIMPLE,
+ &bval, NULL, NULL, NULL);
+# else
+ rc = ldap_bind_s(RebindLDAPHandle, BrowseLDAPBindDN, BrowseLDAPPassword,
+ LDAP_AUTH_SIMPLE);
+# endif /* LDAP_API_VERSION > 3000 */
+
+ return (rc);
+}
+
+
+# else /* defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000) */
+/*
+ * 'ldap_rebind_proc()' - Callback function for LDAP rebind
+ */
+
+static int /* O - Result code */
+ldap_rebind_proc(
+ LDAP *RebindLDAPHandle, /* I - LDAP handle */
+ char **dnp, /* I - ??? */
+ char **passwdp, /* I - ??? */
+ int *authmethodp, /* I - ??? */
+ int freeit, /* I - ??? */
+ void *arg) /* I - ??? */
+{
+ switch (freeit)
+ {
+ case 1:
+ /*
+ * Free current values...
+ */
+
+ debug_printf("cups-browsed: ldap_rebind_proc: Free values...\n");
+
+ if (dnp && *dnp)
+ free(*dnp);
+
+ if (passwdp && *passwdp)
+ free(*passwdp);
+ break;
+
+ case 0:
+ /*
+ * Return credentials for LDAP referal...
+ */
+
+ debug_printf("cups-browsed: "
+ "ldap_rebind_proc: Return necessary values...\n");
+
+ *dnp = strdup(BrowseLDAPBindDN);
+ *passwdp = strdup(BrowseLDAPPassword);
+ *authmethodp = LDAP_AUTH_SIMPLE;
+ break;
+
+ default:
+ /*
+ * Should never happen...
+ */
+
+ fprintf(stderr, "cups-browsed: "
+ "LDAP rebind has been called with wrong freeit value!\n");
+ break;
+ }
+
+ return (LDAP_SUCCESS);
+}
+# endif /* defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000) */
+#endif /* HAVE_LDAP_REBIND_PROC */
+
+
+#ifdef HAVE_LDAP
+/*
+ * 'ldap_connect()' - Start new LDAP connection
+ */
+
+static LDAP * /* O - LDAP handle */
+ldap_connect(void)
+{
+ int rc; /* LDAP API status */
+ int version = 3; /* LDAP version */
+ struct berval bv = {0, ""}; /* SASL bind value */
+ LDAP *TempBrowseLDAPHandle=NULL;
+ /* Temporary LDAP Handle */
+# if defined(HAVE_LDAP_SSL) && defined (HAVE_MOZILLA_LDAP)
+ int ldap_ssl = 0; /* LDAP SSL indicator */
+ int ssl_err = 0; /* LDAP SSL error value */
+# endif /* defined(HAVE_LDAP_SSL) && defined (HAVE_MOZILLA_LDAP) */
+
+
+# ifdef HAVE_OPENLDAP
+# ifdef HAVE_LDAP_SSL
+ /*
+ * Set the certificate file to use for encrypted LDAP sessions...
+ */
+
+ if (BrowseLDAPCACertFile)
+ {
+ debug_printf("cups-browsed: "
+ "ldap_connect: Setting CA certificate file \"%s\"\n",
+ BrowseLDAPCACertFile);
+
+ if ((rc = ldap_set_option(NULL, LDAP_OPT_X_TLS_CACERTFILE,
+ (void *)BrowseLDAPCACertFile)) != LDAP_SUCCESS)
+ fprintf(stderr, "cups-browsed: "
+ "Unable to set CA certificate file for LDAP "
+ "connections: %d - %s\n", rc, ldap_err2string(rc));
+ }
+# endif /* HAVE_LDAP_SSL */
+
+ /*
+ * Initialize OPENLDAP connection...
+ * LDAP stuff currently only supports ldapi EXTERNAL SASL binds...
+ */
+
+ if (!BrowseLDAPServer || !strcasecmp(BrowseLDAPServer, "localhost"))
+ rc = ldap_initialize(&TempBrowseLDAPHandle, "ldapi:///");
+ else
+ rc = ldap_initialize(&TempBrowseLDAPHandle, BrowseLDAPServer);
+
+# else /* HAVE_OPENLDAP */
+
+ int ldap_port = 0; /* LDAP port */
+ char ldap_protocol[11], /* LDAP protocol */
+ ldap_host[255]; /* LDAP host */
+
+ /*
+ * Split LDAP URI into its components...
+ */
+
+ if (!BrowseLDAPServer)
+ {
+ fprintf(stderr, "cups-browsed: BrowseLDAPServer not configured!\n");
+ fprintf(stderr, "cups-browsed: Disabling LDAP browsing!\n");
+ /*BrowseLocalProtocols &= ~BROWSE_LDAP;*/
+ BrowseRemoteProtocols &= ~BROWSE_LDAP;
+ return (NULL);
+ }
+
+ sscanf(BrowseLDAPServer, "%10[^:]://%254[^:/]:%d", ldap_protocol, ldap_host,
+ &ldap_port);
+
+ if (!strcmp(ldap_protocol, "ldap"))
+ ldap_ssl = 0;
+ else if (!strcmp(ldap_protocol, "ldaps"))
+ ldap_ssl = 1;
+ else
+ {
+ fprintf(stderr, "cups-browsed: Unrecognized LDAP protocol (%s)!\n",
+ ldap_protocol);
+ fprintf(stderr, "cups-browsed: Disabling LDAP browsing!\n");
+ /*BrowseLocalProtocols &= ~BROWSE_LDAP;*/
+ BrowseRemoteProtocols &= ~BROWSE_LDAP;
+ return (NULL);
+ }
+
+ if (ldap_port == 0)
+ {
+ if (ldap_ssl)
+ ldap_port = LDAPS_PORT;
+ else
+ ldap_port = LDAP_PORT;
+ }
+
+ debug_printf("cups-browsed: ldap_connect: PROT:%s HOST:%s PORT:%d\n",
+ ldap_protocol, ldap_host, ldap_port);
+
+ /*
+ * Initialize LDAP connection...
+ */
+
+ if (!ldap_ssl)
+ {
+ if ((TempBrowseLDAPHandle = ldap_init(ldap_host, ldap_port)) == NULL)
+ rc = LDAP_OPERATIONS_ERROR;
+ else
+ rc = LDAP_SUCCESS;
+
+# ifdef HAVE_LDAP_SSL
+ }
+ else
+ {
+ /*
+ * Initialize SSL LDAP connection...
+ */
+
+ if (BrowseLDAPCACertFile)
+ {
+ rc = ldapssl_client_init(BrowseLDAPCACertFile, (void *)NULL);
+ if (rc != LDAP_SUCCESS)
+ {
+ fprintf(stderr, "cups-browsed: "
+ "Failed to initialize LDAP SSL client!\n");
+ rc = LDAP_OPERATIONS_ERROR;
+ }
+ else
+ {
+ if ((TempBrowseLDAPHandle = ldapssl_init(ldap_host, ldap_port,
+ 1)) == NULL)
+ rc = LDAP_OPERATIONS_ERROR;
+ else
+ rc = LDAP_SUCCESS;
+ }
+ }
+ else
+ {
+ fprintf(stderr, "cups-browsed: "
+ "LDAP SSL certificate file/database not configured!\n");
+ rc = LDAP_OPERATIONS_ERROR;
+ }
+
+# else /* HAVE_LDAP_SSL */
+
+ /*
+ * Return error, because client libraries doesn't support SSL
+ */
+
+ fprintf(stderr, "cups-browsed: "
+ "LDAP client libraries do not support SSL\n");
+ rc = LDAP_OPERATIONS_ERROR;
+
+# endif /* HAVE_LDAP_SSL */
+ }
+# endif /* HAVE_OPENLDAP */
+
+ /*
+ * Check return code from LDAP initialize...
+ */
+
+ if (rc != LDAP_SUCCESS)
+ {
+ fprintf(stderr, "cups-browsed: Unable to initialize LDAP!\n");
+
+ if (rc == LDAP_SERVER_DOWN || rc == LDAP_CONNECT_ERROR)
+ fprintf(stderr, "cups-browsed: Temporarily disabling LDAP browsing...\n");
+ else
+ {
+ fprintf(stderr, "cups-browsed: Disabling LDAP browsing!\n");
+
+ /*BrowseLocalProtocols &= ~BROWSE_LDAP;*/
+ BrowseRemoteProtocols &= ~BROWSE_LDAP;
+ }
+
+ ldap_disconnect(TempBrowseLDAPHandle);
+
+ return (NULL);
+ }
+
+ /*
+ * Upgrade LDAP version...
+ */
+
+ if (ldap_set_option(TempBrowseLDAPHandle, LDAP_OPT_PROTOCOL_VERSION,
+ (const void *)&version) != LDAP_SUCCESS)
+ {
+ fprintf(stderr, "cups-browsed: Unable to set LDAP protocol version %d!\n",
+ version);
+ fprintf(stderr, "cups-browsed: Disabling LDAP browsing!\n");
+
+ /*BrowseLocalProtocols &= ~BROWSE_LDAP;*/
+ BrowseRemoteProtocols &= ~BROWSE_LDAP;
+ ldap_disconnect(TempBrowseLDAPHandle);
+
+ return (NULL);
+ }
+
+ /*
+ * Register LDAP rebind procedure...
+ */
+
+# ifdef HAVE_LDAP_REBIND_PROC
+# if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
+
+ rc = ldap_set_rebind_proc(TempBrowseLDAPHandle, &ldap_rebind_proc,
+ (void *)NULL);
+ if (rc != LDAP_SUCCESS)
+ fprintf(stderr, "cups-browsed: "
+ "Setting LDAP rebind function failed with status %d: %s\n",
+ rc, ldap_err2string(rc));
+
+# else
+
+ ldap_set_rebind_proc(TempBrowseLDAPHandle, &ldap_rebind_proc, (void *)NULL);
+
+# endif /* defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000) */
+# endif /* HAVE_LDAP_REBIND_PROC */
+
+ /*
+ * Start LDAP bind...
+ */
+
+# if LDAP_API_VERSION > 3000
+ struct berval bval;
+ bval.bv_val = BrowseLDAPPassword;
+ bval.bv_len = (BrowseLDAPPassword == NULL) ? 0 : strlen(BrowseLDAPPassword);
+
+ if (!BrowseLDAPServer || !strcasecmp(BrowseLDAPServer, "localhost"))
+ rc = ldap_sasl_bind_s(TempBrowseLDAPHandle, NULL, "EXTERNAL", &bv, NULL,
+ NULL, NULL);
+ else
+ rc = ldap_sasl_bind_s(TempBrowseLDAPHandle, BrowseLDAPBindDN, LDAP_SASL_SIMPLE, &bval, NULL, NULL, NULL);
+
+# else
+ rc = ldap_bind_s(TempBrowseLDAPHandle, BrowseLDAPBindDN,
+ BrowseLDAPPassword, LDAP_AUTH_SIMPLE);
+# endif /* LDAP_API_VERSION > 3000 */
+
+ if (rc != LDAP_SUCCESS)
+ {
+ fprintf(stderr, "cups-browsed: LDAP bind failed with error %d: %s\n",
+ rc, ldap_err2string(rc));
+
+# if defined(HAVE_LDAP_SSL) && defined (HAVE_MOZILLA_LDAP)
+ if (ldap_ssl && (rc == LDAP_SERVER_DOWN || rc == LDAP_CONNECT_ERROR))
+ {
+ ssl_err = PORT_GetError();
+ if (ssl_err != 0)
+ fprintf(stderr, "cups-browsed: LDAP SSL error %d: %s\n", ssl_err,
+ ldapssl_err2string(ssl_err));
+ }
+# endif /* defined(HAVE_LDAP_SSL) && defined (HAVE_MOZILLA_LDAP) */
+
+ ldap_disconnect(TempBrowseLDAPHandle);
+
+ return (NULL);
+ }
+
+ debug_printf("cups-browsed: LDAP connection established\n");
+
+ return (TempBrowseLDAPHandle);
+}
+
+
+/*
+ * 'ldap_reconnect()' - Reconnect to LDAP Server
+ */
+
+static LDAP * /* O - New LDAP handle */
+ldap_reconnect(void)
+{
+ LDAP *TempBrowseLDAPHandle = NULL; /* Temp Handle to LDAP server */
+
+
+ /*
+ * Get a new LDAP Handle and replace the global Handle
+ * if the new connection was successful.
+ */
+
+ debug_printf("cups-browsed: Try LDAP reconnect...\n");
+
+ TempBrowseLDAPHandle = ldap_connect();
+
+ if (TempBrowseLDAPHandle != NULL)
+ {
+ if (BrowseLDAPHandle != NULL)
+ ldap_disconnect(BrowseLDAPHandle);
+
+ BrowseLDAPHandle = TempBrowseLDAPHandle;
+ }
+
+ return (BrowseLDAPHandle);
+}
+
+
+/*
+ * 'ldap_disconnect()' - Disconnect from LDAP Server
+ */
+
+static void
+ldap_disconnect(LDAP *ld) /* I - LDAP handle */
+{
+ int rc; /* Return code */
+
+
+ /*
+ * Close LDAP handle...
+ */
+
+# if defined(HAVE_OPENLDAP) && LDAP_API_VERSION > 3000
+ rc = ldap_unbind_ext_s(ld, NULL, NULL);
+# else
+ rc = ldap_unbind_s(ld);
+# endif /* defined(HAVE_OPENLDAP) && LDAP_API_VERSION > 3000 */
+
+ if (rc != LDAP_SUCCESS)
+ fprintf(stderr, "cups-browsed: "
+ "Unbind from LDAP server failed with status %d: %s\n",
+ rc, ldap_err2string(rc));
+}
+
+/*
+ * 'cupsdUpdateLDAPBrowse()' - Scan for new printers via LDAP...
+ */
+
+void
+cupsdUpdateLDAPBrowse(void)
+{
+ char uri[HTTP_MAX_URI], /* Printer URI */
+ host[HTTP_MAX_URI], /* Hostname */
+ resource[HTTP_MAX_URI], /* Resource path */
+ local_resource[HTTP_MAX_URI], /* Resource path */
+ location[1024], /* Printer location */
+ info[1024], /* Printer information */
+ make_model[1024], /* Printer make and model */
+ type_num[30], /* Printer type number */
+ scheme[32], /* URI's scheme */
+ username[64]; /* URI's username */
+ int port; /* URI's port number */
+ char *c;
+ int rc; /* LDAP status */
+ int limit; /* Size limit */
+ LDAPMessage *res, /* LDAP search results */
+ *e; /* Current entry from search */
+
+ debug_printf("cups-browsed: UpdateLDAPBrowse\n");
+
+ /*
+ * Reconnect if LDAP Handle is invalid...
+ */
+
+ if (! BrowseLDAPHandle)
+ {
+ ldap_reconnect();
+ return;
+ }
+
+ /*
+ * Search for cups printers in LDAP directory...
+ */
+
+ rc = ldap_search_rec(BrowseLDAPHandle, BrowseLDAPDN, LDAP_SCOPE_SUBTREE,
+ BrowseLDAPFilter, (char **)ldap_attrs, 0, &res);
+
+ /*
+ * If ldap search was successfull then exit function
+ * and temporary disable LDAP updates...
+ */
+
+ if (rc != LDAP_SUCCESS)
+ {
+ if (BrowseLDAPUpdate && ((rc == LDAP_SERVER_DOWN) || (rc == LDAP_CONNECT_ERROR)))
+ {
+ BrowseLDAPUpdate = FALSE;
+ debug_printf("cups-browsed: "
+ "LDAP update temporary disabled\n");
+ }
+ return;
+ }
+
+ /*
+ * If LDAP updates were disabled, we will reenable them...
+ */
+
+ if (! BrowseLDAPUpdate)
+ {
+ BrowseLDAPUpdate = TRUE;
+ debug_printf("cups-browsed: "
+ "LDAP update enabled\n");
+ }
+
+ /*
+ * Count LDAP entries and return if no entry exist...
+ */
+
+ limit = ldap_count_entries(BrowseLDAPHandle, res);
+ debug_printf("cups-browsed: LDAP search returned %d entries\n", limit);
+ if (limit < 1)
+ {
+ ldap_freeres(res);
+ return;
+ }
+
+ /*
+ * Loop through the available printers...
+ */
+
+ for (e = ldap_first_entry(BrowseLDAPHandle, res);
+ e;
+ e = ldap_next_entry(BrowseLDAPHandle, e))
+ {
+ /*
+ * Get the required values from this entry...
+ */
+
+ if (ldap_getval_firststring(BrowseLDAPHandle, e,
+ "printerDescription", info, sizeof(info)) == -1)
+ continue;
+
+ if (ldap_getval_firststring(BrowseLDAPHandle, e,
+ "printerLocation", location, sizeof(location)) == -1)
+ continue;
+
+ if (ldap_getval_firststring(BrowseLDAPHandle, e,
+ "printerMakeAndModel", make_model, sizeof(make_model)) == -1)
+ continue;
+
+ if (ldap_getval_firststring(BrowseLDAPHandle, e,
+ "printerType", type_num, sizeof(type_num)) == -1)
+ continue;
+
+ if (ldap_getval_firststring(BrowseLDAPHandle, e,
+ "printerURI", uri, sizeof(uri)) == -1)
+ continue;
+
+ /*
+ * Process the entry...
+ */
+
+ memset(scheme, 0, sizeof(scheme));
+ memset(username, 0, sizeof(username));
+ memset(host, 0, sizeof(host));
+ memset(resource, 0, sizeof(resource));
+ memset(local_resource, 0, sizeof(local_resource));
+
+ httpSeparateURI (HTTP_URI_CODING_ALL, uri,
+ scheme, sizeof(scheme) - 1,
+ username, sizeof(username) - 1,
+ host, sizeof(host) - 1,
+ &port,
+ resource, sizeof(resource)- 1);
+
+ if (strncasecmp (resource, "/printers/", 10) &&
+ strncasecmp (resource, "/classes/", 9)) {
+ debug_printf("cups-browsed: don't understand URI: %s\n", uri);
+ return;
+ }
+
+ strncpy (local_resource, resource + 1, sizeof (local_resource) - 1);
+ local_resource[sizeof (local_resource) - 1] = '\0';
+ c = strchr (local_resource, '?');
+ if (c)
+ *c = '\0';
+
+ debug_printf("cups-browsed: browsed LDAP queue name is %s\n",
+ local_resource + 9);
+
+ generate_local_queue(host, port, local_resource, info, "", "", NULL);
+
+ }
+
+ ldap_freeres(res);
+}
+
+/*
+ * 'ldap_search_rec()' - LDAP Search with reconnect
+ */
+
+static int /* O - Return code */
+ldap_search_rec(LDAP *ld, /* I - LDAP handler */
+ char *base, /* I - Base dn */
+ int scope, /* I - LDAP search scope */
+ char *filter, /* I - Filter string */
+ char *attrs[], /* I - Requested attributes */
+ int attrsonly, /* I - Return only attributes? */
+ LDAPMessage **res) /* I - LDAP handler */
+{
+ int rc; /* Return code */
+ LDAP *ldr; /* LDAP handler after reconnect */
+
+
+# if defined(HAVE_OPENLDAP) && LDAP_API_VERSION > 3000
+ rc = ldap_search_ext_s(ld, base, scope, filter, attrs, attrsonly, NULL, NULL,
+ NULL, LDAP_NO_LIMIT, res);
+# else
+ rc = ldap_search_s(ld, base, scope, filter, attrs, attrsonly, res);
+# endif /* defined(HAVE_OPENLDAP) && LDAP_API_VERSION > 3000 */
+
+ /*
+ * If we have a connection problem try again...
+ */
+
+ if (rc == LDAP_SERVER_DOWN || rc == LDAP_CONNECT_ERROR)
+ {
+ fprintf(stderr, "cups-browsed: "
+ "LDAP search failed with status %d: %s\n",
+ rc, ldap_err2string(rc));
+ debug_printf("cups-browsed: "
+ "We try the LDAP search once again after reconnecting to "
+ "the server\n");
+ ldap_freeres(*res);
+ ldr = ldap_reconnect();
+
+# if defined(HAVE_OPENLDAP) && LDAP_API_VERSION > 3000
+ rc = ldap_search_ext_s(ldr, base, scope, filter, attrs, attrsonly, NULL,
+ NULL, NULL, LDAP_NO_LIMIT, res);
+# else
+ rc = ldap_search_s(ldr, base, scope, filter, attrs, attrsonly, res);
+# endif /* defined(HAVE_OPENLDAP) && LDAP_API_VERSION > 3000 */
+ }
+
+ if (rc == LDAP_NO_SUCH_OBJECT)
+ debug_printf("cups-browsed: "
+ "ldap_search_rec: LDAP entry/object not found\n");
+ else if (rc != LDAP_SUCCESS)
+ fprintf(stderr, "cups-browsed: "
+ "ldap_search_rec: LDAP search failed with status %d: %s\n",
+ rc, ldap_err2string(rc));
+
+ if (rc != LDAP_SUCCESS)
+ ldap_freeres(*res);
+
+ return (rc);
+}
+
+
+/*
+ * 'ldap_freeres()' - Free LDAPMessage
+ */
+
+static void
+ldap_freeres(LDAPMessage *entry) /* I - LDAP handler */
+{
+ int rc; /* Return value */
+
+
+ rc = ldap_msgfree(entry);
+ if (rc == -1)
+ fprintf(stderr, "cups-browsed: Can't free LDAPMessage!\n");
+ else if (rc == 0)
+ debug_printf("cups-browsed: Freeing LDAPMessage was unnecessary\n");
+}
+
+
+/*
+ * 'ldap_getval_char()' - Get first LDAP value and convert to string
+ */
+
+static int /* O - Return code */
+ldap_getval_firststring(
+ LDAP *ld, /* I - LDAP handler */
+ LDAPMessage *entry, /* I - LDAP message or search result */
+ char *attr, /* I - the wanted attribute */
+ char *retval, /* O - String to return */
+ unsigned long maxsize) /* I - Max string size */
+{
+ char *dn; /* LDAP DN */
+ int rc = 0; /* Return code */
+# if defined(HAVE_OPENLDAP) && LDAP_API_VERSION > 3000
+ struct berval **bval; /* LDAP value array */
+ unsigned long size; /* String size */
+
+
+ /*
+ * Get value from LDAPMessage...
+ */
+
+ if ((bval = ldap_get_values_len(ld, entry, attr)) == NULL)
+ {
+ rc = -1;
+ dn = ldap_get_dn(ld, entry);
+ fprintf(stderr, "cups-browsed: "
+ "Failed to get LDAP value %s for %s!\n",
+ attr, dn);
+ ldap_memfree(dn);
+ }
+ else
+ {
+ /*
+ * Check size and copy value into our string...
+ */
+
+ size = maxsize;
+ if (size < (bval[0]->bv_len + 1))
+ {
+ rc = -1;
+ dn = ldap_get_dn(ld, entry);
+ fprintf(stderr, "cups-browsed: "
+ "Attribute %s is too big! (dn: %s)\n",
+ attr, dn);
+ ldap_memfree(dn);
+ }
+ else
+ size = bval[0]->bv_len + 1;
+
+ strncpy(retval, bval[0]->bv_val, size);
+ if (size > 0)
+ retval[size - 1] = '\0';
+ ldap_value_free_len(bval);
+ }
+# else
+ char **value; /* LDAP value */
+
+ /*
+ * Get value from LDAPMessage...
+ */
+
+ if ((value = (char **)ldap_get_values(ld, entry, attr)) == NULL)
+ {
+ rc = -1;
+ dn = ldap_get_dn(ld, entry);
+ fprintf(stderr, "cups-browsed: Failed to get LDAP value %s for %s!\n",
+ attr, dn);
+ ldap_memfree(dn);
+ }
+ else
+ {
+ strncpy(retval, *value, maxsize);
+ if (maxsize > 0)
+ retval[maxsize - 1] = '\0';
+ ldap_value_free(value);
+ }
+# endif /* defined(HAVE_OPENLDAP) && LDAP_API_VERSION > 3000 */
+
+ return (rc);
+}
+
+#endif /* HAVE_LDAP */
+
+
+static int
+create_subscription ()
+{
+ ipp_t *req;
+ ipp_t *resp;
+ ipp_attribute_t *attr;
+ int id = 0;
+
+ req = ippNewRequest (IPP_CREATE_PRINTER_SUBSCRIPTION);
+ ippAddString (req, IPP_TAG_OPERATION, IPP_TAG_URI,
+ "printer-uri", NULL, "/");
+ ippAddString (req, IPP_TAG_SUBSCRIPTION, IPP_TAG_KEYWORD,
+ "notify-events", NULL, "all");
+ ippAddString (req, IPP_TAG_SUBSCRIPTION, IPP_TAG_URI,
+ "notify-recipient-uri", NULL, "dbus://");
+ ippAddInteger (req, IPP_TAG_SUBSCRIPTION, IPP_TAG_INTEGER,
+ "notify-lease-duration", NOTIFY_LEASE_DURATION);
+
+ resp = cupsDoRequest (CUPS_HTTP_DEFAULT, req, "/");
+ if (!resp || cupsLastError() != IPP_OK) {
+ g_warning ("Error subscribing to CUPS notifications: %s\n",
+ cupsLastErrorString ());
+ return 0;
+ }
+
+ attr = ippFindAttribute (resp, "notify-subscription-id", IPP_TAG_INTEGER);
+ if (attr)
+ id = ippGetInteger (attr, 0);
+ else
+ g_warning ("ipp-create-printer-subscription response doesn't contain "
+ "subscription id.\n");
+
+ ippDelete (resp);
+ return id;
+}
+
+
+static gboolean
+renew_subscription (int id)
+{
+ ipp_t *req;
+ ipp_t *resp;
+
+ req = ippNewRequest (IPP_RENEW_SUBSCRIPTION);
+ ippAddInteger (req, IPP_TAG_OPERATION, IPP_TAG_INTEGER,
+ "notify-subscription-id", id);
+ ippAddString (req, IPP_TAG_OPERATION, IPP_TAG_URI,
+ "printer-uri", NULL, "/");
+ ippAddString (req, IPP_TAG_SUBSCRIPTION, IPP_TAG_URI,
+ "notify-recipient-uri", NULL, "dbus://");
+ ippAddInteger (req, IPP_TAG_SUBSCRIPTION, IPP_TAG_INTEGER,
+ "notify-lease-duration", NOTIFY_LEASE_DURATION);
+
+ resp = cupsDoRequest (CUPS_HTTP_DEFAULT, req, "/");
+ if (!resp || cupsLastError() != IPP_OK) {
+ g_warning ("Error renewing CUPS subscription %d: %s\n",
+ id, cupsLastErrorString ());
+ return FALSE;
+ }
+
+ ippDelete (resp);
+ return TRUE;
+}
+
+
+static gboolean
+renew_subscription_timeout (gpointer userdata)
+{
+ int *subscription_id = userdata;
+
+ if (*subscription_id <= 0 || !renew_subscription (*subscription_id))
+ *subscription_id = create_subscription ();
+
+ return TRUE;
+}
+
+
+void
+cancel_subscription (int id)
+{
+ ipp_t *req;
+ ipp_t *resp;
+
+ if (id <= 0)
+ return;
+
+ req = ippNewRequest (IPP_CANCEL_SUBSCRIPTION);
+ ippAddString (req, IPP_TAG_OPERATION, IPP_TAG_URI,
+ "printer-uri", NULL, "/");
+ ippAddInteger (req, IPP_TAG_OPERATION, IPP_TAG_INTEGER,
+ "notify-subscription-id", id);
+
+ resp = cupsDoRequest (CUPS_HTTP_DEFAULT, req, "/");
+ if (!resp || cupsLastError() != IPP_OK) {
+ g_warning ("Error subscribing to CUPS notifications: %s\n",
+ cupsLastErrorString ());
+ return;
+ }
+
+ ippDelete (resp);
+}
+
+int
+set_cups_default_printer(const char *printer) {
+ ipp_t *request;
+ char uri[HTTP_MAX_URI];
+
+ if (printer == NULL)
+ return 0;
+ httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
+ "localhost", 0, "/printers/%s", printer);
+ request = ippNewRequest(IPP_OP_CUPS_SET_DEFAULT);
+ 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());
+ ippDelete(cupsDoRequest(CUPS_HTTP_DEFAULT, request, "/admin/"));
+ if (cupsLastError() > IPP_STATUS_OK_CONFLICTING) {
+ debug_printf("cups-browsed: ERROR: Failed setting CUPS default printer to '%s': %s\n",
+ printer, cupsLastErrorString());
+ return -1;
+ }
+ debug_printf("cups-browsed: Successfully set CUPS default printer to '%s'\n",
+ printer);
+ return 0;
+}
+
+const char*
+get_cups_default_printer() {
+ ipp_t *request, *response;
+ ipp_attribute_t *attr;
+ const char *default_printer_name = NULL;
+
+ request = ippNewRequest(CUPS_GET_DEFAULT);
+ /* Default user */
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
+ "requesting-user-name", NULL, cupsUser());
+ /* Do it */
+ response = cupsDoRequest(CUPS_HTTP_DEFAULT, request, "/");
+ if (cupsLastError() > IPP_OK_CONFLICT || !response) {
+ debug_printf("cups-browsed: Could not determine system default printer!\n");
+ } else {
+ for (attr = ippFirstAttribute(response); attr != NULL;
+ attr = ippNextAttribute(response)) {
+ while (attr != NULL && ippGetGroupTag(attr) != IPP_TAG_PRINTER)
+ attr = ippNextAttribute(response);
+ if (attr) {
+ for (; attr && ippGetGroupTag(attr) == IPP_TAG_PRINTER;
+ attr = ippNextAttribute(response)) {
+ if (!strcasecmp(ippGetName(attr), "printer-name") &&
+ ippGetValueTag(attr) == IPP_TAG_NAME) {
+ default_printer_name = ippGetString(attr, 0, NULL);
+ break;
+ }
+ }
+ }
+ if (default_printer_name)
+ break;
+ }
+ }
+ return default_printer_name;
+}
+
+int
+is_cups_default_printer(const char *printer) {
+ if (printer == NULL)
+ return 0;
+ const char *cups_default = get_cups_default_printer();
+ if (cups_default == NULL)
+ return 0;
+ if (!strcasecmp(printer, cups_default))
+ return 1;
+ return 0;
+}
+
+int
+invalidate_default_printer(int local) {
+ const char *filename = local ? LOCAL_DEFAULT_PRINTER_FILE :
+ REMOTE_DEFAULT_PRINTER_FILE;
+ unlink(filename);
+ return 0;
+}
+
+int
+record_default_printer(const char *printer, int local) {
+ FILE *fp = NULL;
+ const char *filename = local ? LOCAL_DEFAULT_PRINTER_FILE :
+ REMOTE_DEFAULT_PRINTER_FILE;
+
+ if (printer == NULL)
+ return invalidate_default_printer(local);
+
+ fp = fopen(filename, "w+");
+ if (fp == NULL) {
+ debug_printf("cups-browsed: ERROR: Failed creating file %s\n",
+ filename);
+ return -1;
+ }
+ fprintf(fp, "%s", printer);
+ fclose(fp);
+
+ return 0;
+}
+
+const char*
+retrieve_default_printer(int local) {
+ FILE *fp = NULL;
+ const char *filename = local ? LOCAL_DEFAULT_PRINTER_FILE :
+ REMOTE_DEFAULT_PRINTER_FILE;
+ const char *printer = NULL;
+ char *p, buf[1024];
+ int n;
+
+ fp = fopen(filename, "r");
+ if (fp == NULL) {
+ debug_printf("cups-browsed: Failed reading file %s\n",
+ filename);
+ return NULL;
+ }
+ p = buf;
+ n = fscanf(fp, "%s", p);
+ if (n == 1) {
+ if (strlen(p) > 0)
+ printer = p;
+ }
+ fclose(fp);
+
+ return printer;
+}
+
+int
+is_created_by_cups_browsed (const char *printer) {
+ remote_printer_t *p;
+
+ if (printer == NULL)
+ return 0;
+ for (p = (remote_printer_t *)cupsArrayFirst(remote_printers);
+ p; p = (remote_printer_t *)cupsArrayNext(remote_printers))
+ if (!strcasecmp(printer, p->name))
+ return 1;
+
+ return 0;
+}
+
+remote_printer_t *
+printer_record (const char *printer) {
+ remote_printer_t *p;
+
+ if (printer == NULL)
+ return NULL;
+ for (p = (remote_printer_t *)cupsArrayFirst(remote_printers);
+ p; p = (remote_printer_t *)cupsArrayNext(remote_printers))
+ if (!strcasecmp(printer, p->name))
+ return p;
+
+ return NULL;
+}
+
+int
+queue_creation_handle_default(const char *printer) {
+ /* If this queue is recorded as the former default queue (and the current
+ default is local), set it as default (the CUPS notification handler
+ will record the local default printer then) */
+ const char *recorded_default = retrieve_default_printer(0);
+ if (recorded_default == NULL || strcasecmp(recorded_default, printer))
+ return 0;
+ const char *current_default = get_cups_default_printer();
+ if (current_default == NULL || !is_created_by_cups_browsed(current_default)) {
+ if (set_cups_default_printer(printer) < 0) {
+ debug_printf("cups-browsed: ERROR: Could not set former default printer %s as default again.\n",
+ printer);
+ return -1;
+ } else {
+ debug_printf("cups-browsed: Former default printer %s re-appeared, set as default again.\n",
+ printer);
+ invalidate_default_printer(0);
+ }
+ }
+ return 0;
+}
+
+int
+queue_removal_handle_default(const char *printer) {
+ /* If the queue is the default printer, get back
+ to the recorded local default printer, record this queue for getting the
+ default set to this queue again if it re-appears. */
+ /* We call this also if a queue is only conserved because on cups-browsed
+ shutdown it still has jobs */
+ if (!is_cups_default_printer(printer))
+ return 0;
+ /* Record the fact that this printer was default */
+ if (record_default_printer(default_printer, 0) < 0) {
+ /* Delete record file if recording failed */
+ debug_printf("cups-browsed: ERROR: Failed recording remote default printer (%s). Removing the file with possible old recording.\n",
+ printer);
+ invalidate_default_printer(0);
+ } else
+ debug_printf("cups-browsed: Recorded the fact that the current printer (%s) is the default printer before deleting the queue and returning to the local default printer.\n",
+ printer);
+ /* Switch back to a recorded local printer, if available */
+ const char *local_default = retrieve_default_printer(1);
+ if (local_default != NULL) {
+ if (set_cups_default_printer(local_default) >= 0)
+ debug_printf("cups-browsed: Switching back to %s as default printer.\n",
+ local_default);
+ else {
+ debug_printf("cups-browsed: ERROR: Unable to switch back to %s as default printer.\n",
+ local_default);
+ return -1;
+ }
+ }
+ invalidate_default_printer(1);
+ return 0;
+}
+
+static void
+on_printer_state_changed (CupsNotifier *object,
+ const gchar *text,
+ const gchar *printer_uri,
+ const gchar *printer,
+ guint printer_state,
+ const gchar *printer_state_reasons,
+ gboolean printer_is_accepting_jobs,
+ gpointer user_data)
+{
+ char *ptr, buf[1024];
+ remote_printer_t *p;
+ char server_str[1024];
+ ipp_t *request, *response;
+ ipp_attribute_t *attr;
+ const char *pname = NULL;
+ ipp_pstate_t pstate = IPP_PRINTER_IDLE;
+ int num_jobs, min_jobs = 99999999;
+ cups_job_t *jobs = NULL;
+ const char *dest_host = NULL;
+ char filename[1024];
+ FILE *fp;
+ static const char *pattrs[] =
+ {
+ "printer-name",
+ "printer-state"
+ };
+
+ debug_printf("cups-browsed: [CUPS Notification] Printer state change: %s\n",
+ text);
+ if ((ptr = strstr(text, " is now the default printer")) != NULL) {
+ /* Default printer has changed, we are triggered by the new default
+ printer */
+ strncpy(buf, text, ptr - text);
+ buf[ptr - text] = '\0';
+ debug_printf("cups-browsed: [CUPS Notification] Default printer changed from %s to %s.\n",
+ default_printer, buf);
+ if (is_created_by_cups_browsed(default_printer)) {
+ /* Previous default printer created by cups-browsed */
+ if (!is_created_by_cups_browsed(buf)) {
+ /* New default printer local */
+ /* Removed backed-up local default printer as we do not have a
+ remote printer as default any more */
+ invalidate_default_printer(1);
+ debug_printf("cups-browsed: Manually switched default printer from a cups-browsed-generated one to a local printer.\n");
+ }
+ } else {
+ /* Previous default printer local */
+ if (is_created_by_cups_browsed(buf)) {
+ /* New default printer created by cups-browsed */
+ /* Back up the local default printer to be able to return to it
+ if the remote printer disappears */
+ if (record_default_printer(default_printer, 1) < 0) {
+ /* Delete record file if recording failed */
+ debug_printf("cups-browsed: ERROR: Failed recording local default printer. Removing the file with possible old recording.\n");
+ invalidate_default_printer(1);
+ } else
+ debug_printf("cups-browsed: Recorded previous default printer so that if the currently selected cups-browsed-generated one disappears, we can return to the old local one.\n");
+ /* Remove a recorded remote printer as after manually selecting
+ another one as default this one is not relevant any more */
+ invalidate_default_printer(0);
+ }
+ }
+ if (default_printer != NULL)
+ free((void *)default_printer);
+ default_printer = strdup(buf);
+ } else if ((ptr = strstr(text, " is no longer the default printer"))
+ != NULL) {
+ /* Default printer has changed, we are triggered by the former default
+ printer */
+ strncpy(buf, text, ptr - text);
+ buf[ptr - text] = '\0';
+ debug_printf("cups-browsed: [CUPS Notification] %s not default printer any more.\n", buf);
+ } else if ((ptr = strstr(text, " state changed to processing")) != NULL) {
+ /* Printer started processing a job, check if it uses the implicitclass
+ backend and if so, check all remote printers assigned to itself and
+ to its duplicates which is the most suitable to send the job to (in
+ terms of being enabled and minimum number of queued jobs). Supply
+ the appropriate device URI to the backend. */
+ debug_printf("cups-browsed: [CUPS Notification] %s starts processing a job.\n", printer);
+ p = printer_record(printer);
+ if (p->num_duplicates > 0) {
+ debug_printf("cups-browsed: [CUPS Notification] %s is using the \"implicitclass\" CUPS backend, so let us search a destination for this job.\n", printer);
+ for (p = (remote_printer_t *)cupsArrayFirst(remote_printers);
+ p; p = (remote_printer_t *)cupsArrayNext(remote_printers)) {
+ if (!strcasecmp(p->name, printer) &&
+ p->status == STATUS_CONFIRMED) {
+ debug_printf("cups-browsed: Checking state and number of jobs of remote printer %s on host %s.\n", printer, p->host);
+ snprintf(server_str, sizeof(server_str), "%s:%d", p->host, ippPort());
+ cupsSetServer(server_str);
+ /* Check whether the printer is idle, processing, or disabled */
+ request = ippNewRequest(CUPS_GET_PRINTERS);
+ ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
+ "requested-attributes",
+ sizeof(pattrs) / sizeof(pattrs[0]),
+ NULL, pattrs);
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
+ "requesting-user-name",
+ NULL, cupsUser());
+ if ((response = cupsDoRequest(CUPS_HTTP_DEFAULT, request, "/")) !=
+ NULL) {
+ for (attr = ippFirstAttribute(response); attr != NULL;
+ attr = ippNextAttribute(response)) {
+ while (attr != NULL && ippGetGroupTag(attr) != IPP_TAG_PRINTER)
+ attr = ippNextAttribute(response);
+ if (attr == NULL)
+ break;
+ pname = NULL;
+ pstate = IPP_PRINTER_IDLE;
+ while (attr != NULL && ippGetGroupTag(attr) ==
+ IPP_TAG_PRINTER) {
+ if (!strcmp(ippGetName(attr), "printer-name") &&
+ ippGetValueTag(attr) == IPP_TAG_NAME)
+ pname = ippGetString(attr, 0, NULL);
+ else if (!strcmp(ippGetName(attr), "printer-state") &&
+ ippGetValueTag(attr) == IPP_TAG_ENUM)
+ pstate = (ipp_pstate_t)ippGetInteger(attr, 0);
+ attr = ippNextAttribute(response);
+ }
+ if (pname == NULL) {
+ if (attr == NULL)
+ break;
+ else
+ continue;
+ }
+ if (!strcasecmp(pname, printer)) {
+ switch (pstate) {
+ case IPP_PRINTER_IDLE:
+ dest_host = p->host;
+ debug_printf("cups-browsed: Printer %s on host %s is idle, take this as destination and stop searching.\n", printer, p->host);
+ break;
+ case IPP_PRINTER_PROCESSING:
+ num_jobs = 0;
+ jobs = NULL;
+ num_jobs =
+ cupsGetJobs2(CUPS_HTTP_DEFAULT, &jobs, printer, 0,
+ CUPS_WHICHJOBS_ACTIVE);
+ if (num_jobs >= 0 && num_jobs < min_jobs) {
+ min_jobs = num_jobs;
+ dest_host = p->host;
+ }
+ debug_printf("cups-browsed: Printer %s on host %s is printing and it has %d jobs.\n", printer, p->host, num_jobs);
+ break;
+ case IPP_PRINTER_STOPPED:
+ debug_printf("cups-browsed: Printer %s on host %s is disabled, skip it.\n", printer, p->host);
+ break;
+ }
+ break;
+ }
+ }
+ if (pstate == IPP_PRINTER_IDLE)
+ break;
+ }
+ }
+ }
+ snprintf(filename, sizeof(filename), IMPLICIT_CLASS_DEST_HOST_FILE,
+ printer);
+ fp = fopen(filename, "w+");
+ if (fp == NULL) {
+ debug_printf("cups-browsed: ERROR: Failed creating file %s\n",
+ filename);
+ return;
+ }
+ if (dest_host) {
+ fprintf(fp, "\"%s\"", dest_host);
+ debug_printf("cups-browsed: Wrote destination for job to %s: %s (to file %s)\n",
+ printer, dest_host, filename);
+ } else {
+ fprintf(fp, "\"NO_DEST_FOUND\"");
+ debug_printf("cups-browsed: ERROR: No destination found for job to %s (file %s)\n",
+ printer, filename);
+ }
+ fclose(fp);
+ }
+ }
+}
+
+static void
+on_printer_deleted (CupsNotifier *object,
+ const gchar *text,
+ const gchar *printer_uri,
+ const gchar *printer,
+ guint printer_state,
+ const gchar *printer_state_reasons,
+ gboolean printer_is_accepting_jobs,
+ gpointer user_data)
+{
+ remote_printer_t *p;
+ const char* r;
+
+ debug_printf("cups-browsed: [CUPS Notification] Printer deleted: %s\n",
+ text);
+
+ if (is_created_by_cups_browsed(printer)) {
+ /* a cups-browsed-generated printer got deleted, re-create it */
+ debug_printf("cups-browsed: Printer %s got deleted, re-creating it.\n",
+ printer);
+ /* If the deleted printer was the default printer, make sure it gets the
+ default printer again */
+ if (default_printer && !strcasecmp(printer, default_printer)) {
+ if (record_default_printer(printer, 0) < 0) {
+ /* Delete record file if recording failed */
+ debug_printf("cups-browsed: ERROR: Failed recording remote default printer. Removing the file with possible old recording.\n");
+ invalidate_default_printer(0);
+ } else
+ debug_printf("cups-browsed: Recorded %s as remote default printer so that it gets set as default after re-creating.\n");
+ /* Make sure that a recorded local default printer does not get lost
+ during the recovery operation */
+ if ((r = retrieve_default_printer(1)) != NULL) {
+ if (default_printer != NULL)
+ free((void *)default_printer);
+ default_printer = strdup(r);
+ }
+ }
+ /* Schedule for immediate creation of the CUPS queue */
+ p = printer_record(printer);
+ if (p) {
+ p->status = STATUS_TO_BE_CREATED;
+ p->timeout = time(NULL) + TIMEOUT_IMMEDIATELY;
+ recheck_timer();
+ }
+ }
+}
+
+
static remote_printer_t *
create_local_queue (const char *name,
const char *uri,
@@ -757,6 +2135,9 @@ create_local_queue (const char *name,
if (!p->uri)
goto fail;
+ p->duplicate_of = NULL;
+ p->num_duplicates = 0;
+
p->num_options = 0;
p->options = NULL;
@@ -793,17 +2174,28 @@ create_local_queue (const char *name,
for (q = (remote_printer_t *)cupsArrayFirst(remote_printers);
q;
q = (remote_printer_t *)cupsArrayNext(remote_printers))
- if (!strcasecmp(q->name, p->name))
+ if (!strcasecmp(q->name, p->name) &&
+ q != p)
break;
- p->duplicate = (q && q->status != STATUS_DISAPPEARED &&
- q->status != STATUS_UNCONFIRMED) ? 1 : 0;
- if (p->duplicate)
+ p->duplicate_of = (q && q->status != STATUS_DISAPPEARED &&
+ q->status != STATUS_UNCONFIRMED) ? q : NULL;
+ if (p->duplicate_of) {
debug_printf("cups-browsed: Printer %s already available through host %s.\n",
p->name, q->host);
- else if (q) {
- q->duplicate = 1;
+ if (!q->duplicate_of) {
+ /* Update q to get implicitclass:... URI */
+ q->num_duplicates ++;
+ q->status = STATUS_TO_BE_CREATED;
+ q->timeout = time(NULL) + TIMEOUT_IMMEDIATELY;
+ }
+ } else if (q) {
+ q->duplicate_of = p;
debug_printf("cups-browsed: Unconfirmed/disappeared printer %s already available through host %s, marking that printer duplicate of the newly found one.\n",
p->name, q->host);
+ /* Update p to get implicitclass:... URI */
+ p->num_duplicates ++;
+ p->status = STATUS_TO_BE_CREATED;
+ p->timeout = time(NULL) + TIMEOUT_IMMEDIATELY;
}
} else {
#ifndef HAVE_CUPS_1_6
@@ -837,7 +2229,8 @@ create_local_queue (const char *name,
goto fail;
}
- p->duplicate = 0;
+ p->duplicate_of = NULL;
+ p->num_duplicates = 0;
p->model = NULL;
/* Request printer properties and try to generate a PPD file for the
@@ -1147,17 +2540,15 @@ remove_bad_chars(const char *str_orig, /* I - Original string */
}
gboolean handle_cups_queues(gpointer unused) {
- remote_printer_t *p;
+ remote_printer_t *p, *q;
http_t *http;
- char uri[HTTP_MAX_URI];
+ char uri[HTTP_MAX_URI], device_uri[HTTP_MAX_URI];
int num_options;
cups_option_t *options;
int num_jobs;
cups_job_t *jobs;
- ipp_t *request, *response;
+ ipp_t *request;
time_t current_time = time(NULL);
- const char *default_printer_name;
- ipp_attribute_t *attr;
int i;
debug_printf("cups-browsed: Processing printer list ...\n");
@@ -1188,10 +2579,10 @@ gboolean handle_cups_queues(gpointer unused) {
break;
debug_printf("cups-browsed: Removing entry %s%s.\n", p->name,
- (p->duplicate ? "" : " and its CUPS queue"));
+ (p->duplicate_of ? "" : " and its CUPS queue"));
/* Remove the CUPS queue */
- if (!p->duplicate) { /* Duplicates do not have a CUPS queue */
+ if (!p->duplicate_of) { /* Duplicates do not have a CUPS queue */
if ((http = http_connect_local ()) == NULL) {
debug_printf("cups-browsed: Unable to connect to CUPS!\n");
p->timeout = current_time + TIMEOUT_RETRY;
@@ -1211,49 +2602,12 @@ gboolean handle_cups_queues(gpointer unused) {
break;
}
- /* Check whether the queue is the system default. In this case do not
- remove it, so that this user setting does not get lost */
- default_printer_name = NULL;
- request = ippNewRequest(CUPS_GET_DEFAULT);
- /* Default user */
- ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
- "requesting-user-name", NULL, cupsUser());
- /* Do it */
- response = cupsDoRequest(http, request, "/");
- if (cupsLastError() > IPP_OK_CONFLICT || !response) {
- debug_printf("cups-browsed: Could not determine system default printer!\n");
- } else {
- for (attr = ippFirstAttribute(response); attr != NULL;
- attr = ippNextAttribute(response)) {
- while (attr != NULL && ippGetGroupTag(attr) != IPP_TAG_PRINTER)
- attr = ippNextAttribute(response);
- if (attr) {
- for (; attr && ippGetGroupTag(attr) == IPP_TAG_PRINTER;
- attr = ippNextAttribute(response)) {
- if (!strcasecmp(ippGetName(attr), "printer-name") &&
- ippGetValueTag(attr) == IPP_TAG_NAME) {
- default_printer_name = ippGetString(attr, 0, NULL);
- break;
- }
- }
- }
- if (default_printer_name)
- break;
- }
- }
- if (default_printer_name &&
- !strcasecmp(default_printer_name, p->name)) {
- /* Printer is currently the system's default printer,
- do not remove it */
- /* Schedule the removal of the queue for later */
- p->timeout = current_time + TIMEOUT_RETRY;
- ippDelete(response);
- break;
- }
- if (response)
- ippDelete(response);
+ /* If this queue was the default printer, note that fact so that
+ it gets the default printer again when it re-appears, also switch
+ back to the last local default printer */
+ queue_removal_handle_default(p->name);
- /* No jobs, not default printer, remove the CUPS queue */
+ /* No jobs, remove the CUPS queue */
request = ippNewRequest(CUPS_DELETE_PRINTER);
/* Printer URI: ipp://localhost:631/printers/<queue name> */
httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
@@ -1270,6 +2624,15 @@ gboolean handle_cups_queues(gpointer unused) {
p->timeout = current_time + TIMEOUT_RETRY;
break;
}
+ } else {
+ /* "master printer" of this duplicate */
+ q = p->duplicate_of;
+ debug_printf("cups-browsed: Removed a duplicate of printer %s on %s, scheduling its master printer %s on host %s for update, to assure it will have the correct device URI.\n",
+ p->name, p->host, q->name, q->host);
+ /* Schedule for update, so that an implicitclass:... URI gets
+ removed if not needed any more */
+ q->status = STATUS_TO_BE_CREATED;
+ q->timeout = time(NULL) + TIMEOUT_IMMEDIATELY;
}
/* CUPS queue removed, remove the list entry */
@@ -1307,7 +2670,8 @@ gboolean handle_cups_queues(gpointer unused) {
case STATUS_BROWSE_PACKET_RECEIVED:
/* Do not create a queue for duplicates */
- if (p->duplicate) {
+ if (p->duplicate_of) {
+ p->status = STATUS_CONFIRMED;
p->timeout = (time_t) -1;
break;
}
@@ -1318,6 +2682,26 @@ gboolean handle_cups_queues(gpointer unused) {
debug_printf("cups-browsed: Creating/Updating CUPS queue for %s\n",
p->name);
+ debug_printf("cups-browsed: Queue has %d duplicates\n",
+ p->num_duplicates);
+
+ /* Determine whether we we have duplicates, and so an implicit class
+ for load balancing. In this case we will assign an implicitclass:...
+ device URI, which makes cups-browsed find the best destination for
+ each job. */
+ if (p->num_duplicates > 0) {
+ /* We have duplicates, so we use the device URI
+ implicitclass:<queue name> */
+ snprintf(device_uri, sizeof(device_uri), "implicitclass:%s",
+ p->name);
+ debug_printf("cups-browsed: Print queue %s has duplicates, using implicit class device URI %s\n",
+ p->name, device_uri);
+ } else {
+ /* Device URI: ipp(s)://<remote host>:631/printers/<remote queue> */
+ strncpy(device_uri, p->uri, sizeof(device_uri));
+ debug_printf("cups-browsed: Print queue %s has no duplicates, using direct device URI %s\n",
+ p->name, device_uri);
+ }
/* Create a new CUPS queue or modify the existing queue */
if ((http = http_connect_local ()) == NULL) {
@@ -1341,8 +2725,9 @@ gboolean handle_cups_queues(gpointer unused) {
ippAddBoolean(request, IPP_TAG_PRINTER, "printer-is-accepting-jobs", 1);
num_options = 0;
options = NULL;
- /* Device URI: ipp(s)://<remote host>:631/printers/<remote queue> */
- num_options = cupsAddOption("device-uri", p->uri,
+ /* Device URI: ipp(s)://<remote host>:631/printers/<remote queue>
+ OR implicitclass:<queue name> */
+ num_options = cupsAddOption("device-uri", device_uri,
num_options, &options);
/* Option cups-browsed=true, marking that we have created this queue */
num_options = cupsAddOption(CUPS_BROWSED_MARK "-default", "true",
@@ -1394,6 +2779,10 @@ gboolean handle_cups_queues(gpointer unused) {
break;
}
+ /* If this queue was the default printer in its previous life, make
+ it the default printer again. */
+ queue_creation_handle_default(p->name);
+
if (p->status == STATUS_BROWSE_PACKET_RECEIVED) {
p->status = STATUS_DISAPPEARED;
p->timeout = time(NULL) + BrowseTimeout;
@@ -1406,8 +2795,11 @@ gboolean handle_cups_queues(gpointer unused) {
break;
- /* Nothing to do */
case STATUS_CONFIRMED:
+ /* If this queue was the default printer in its previous life, make
+ it the default printer again. */
+ queue_creation_handle_default(p->name);
+
break;
}
@@ -1474,7 +2866,7 @@ generate_local_queue(const char *host,
char *backup_queue_name = NULL, *local_queue_name = NULL,
*local_queue_name_lower = NULL;
int is_cups_queue;
- size_t hl = 0;
+ /*size_t hl = 0;*/
gboolean create = TRUE;
@@ -1490,11 +2882,11 @@ generate_local_queue(const char *host,
* strdup() is called inside remove_bad_chars() and result is free()-able.
*/
remote_host = remove_bad_chars(host, 1);
- hl = strlen(remote_host);
+ /*hl = strlen(remote_host);
if (hl > 6 && !strcasecmp(remote_host + hl - 6, ".local"))
remote_host[hl - 6] = '\0';
if (hl > 7 && !strcasecmp(remote_host + hl - 7, ".local."))
- remote_host[hl - 7] = '\0';
+ remote_host[hl - 7] = '\0';*/
/* Check by the resource whether the discovered printer is a CUPS queue */
if (!strncasecmp(resource, "printers/", 9)) {
@@ -1890,7 +3282,7 @@ static void browse_callback(
/* A service (remote printer) has disappeared */
case AVAHI_BROWSER_REMOVE: {
- remote_printer_t *p, *q;
+ remote_printer_t *p, *q, *r;
int i;
/* Ignore events from the local machine */
@@ -1908,15 +3300,27 @@ static void browse_callback(
!strcasecmp(p->domain, domain))
break;
if (p) {
- /* Check whether this queue has a duplicate from another server */
q = NULL;
- if (!p->duplicate) {
+ if (p->duplicate_of) {
+ /* "master printer" of this duplicate */
+ q = p->duplicate_of;
+ debug_printf("cups-browsed: Removing the duplicate printer %s on host %s, scheduling its master printer %s on host %s for update, to assure it will have the correct device URI.\n",
+ p->name, p->host, q->name, q->host);
+ /* Schedule for update, so that an implicitclass:... URI gets
+ removed if not needed any more */
+ q->num_duplicates --;
+ q->status = STATUS_TO_BE_CREATED;
+ q->timeout = time(NULL) + TIMEOUT_IMMEDIATELY;
+ q = NULL;
+ } else {
+ /* Check whether this queue has a duplicate from another server and
+ find it */
for (q = (remote_printer_t *)cupsArrayFirst(remote_printers);
q;
q = (remote_printer_t *)cupsArrayNext(remote_printers))
if (!strcasecmp(q->name, p->name) &&
strcasecmp(q->host, p->host) &&
- q->duplicate)
+ q->duplicate_of)
break;
}
if (q) {
@@ -1936,6 +3340,7 @@ static void browse_callback(
p->service_name = strdup(q->service_name);
p->type = strdup(q->type);
p->domain = strdup(q->domain);
+ p->num_duplicates --;
for (i = 0; i < q->num_options; i ++)
p->num_options = cupsAddOption(strdup(q->options[i].name),
strdup(q->options[i].value),
@@ -1943,6 +3348,13 @@ static void browse_callback(
if (q->ppd) p->ppd = strdup(q->ppd);
if (q->model) p->model = strdup(q->model);
if (q->ifscript) p->ifscript = strdup(q->ifscript);
+ for (r = (remote_printer_t *)cupsArrayFirst(remote_printers);
+ r;
+ r = (remote_printer_t *)cupsArrayNext(remote_printers))
+ if (!strcasecmp(p->name, r->name) &&
+ strcasecmp(p->host, r->host) &&
+ r->duplicate_of)
+ r->duplicate_of = p;
/* Schedule this printer for updating the CUPS queue */
p->status = STATUS_TO_BE_CREATED;
p->timeout = time(NULL) + TIMEOUT_IMMEDIATELY;
@@ -1958,7 +3370,7 @@ static void browse_callback(
p->status = STATUS_DISAPPEARED;
p->timeout = time(NULL) + TIMEOUT_REMOVE;
- debug_printf("cups-browsed: Printer %s (Host: %s, URI: %s) disappeared and no backup available, removing entry.\n",
+ debug_printf("cups-browsed: Printer %s (Host: %s, URI: %s) disappeared and no duplicate available, or a duplicate of another printer, removing entry.\n",
p->name, p->host, p->uri);
}
@@ -2902,6 +4314,77 @@ fail:
return FALSE;
}
+#ifdef HAVE_LDAP
+gboolean
+browse_ldap_poll (gpointer data)
+{
+ char *tmpFilter; /* Query filter */
+ int filterLen;
+
+ /* do real stuff here */
+ if (!BrowseLDAPDN)
+ {
+ fprintf(stderr, "cups-browsed: "
+ "Need to set BrowseLDAPDN to use LDAP browsing!\n");
+ BrowseLocalProtocols &= ~BROWSE_LDAP;
+ BrowseRemoteProtocols &= ~BROWSE_LDAP;
+
+ return FALSE;
+ }
+ else
+ {
+ if (!BrowseLDAPInitialised)
+ {
+ BrowseLDAPInitialised = TRUE;
+ /*
+ * Query filter string
+ */
+ if (BrowseLDAPFilter)
+ filterLen = snprintf(NULL, 0, "(&%s%s)", LDAP_BROWSE_FILTER, BrowseLDAPFilter);
+ else
+ filterLen = strlen(LDAP_BROWSE_FILTER);
+
+ tmpFilter = (char *)malloc(filterLen + 1);
+ if (!tmpFilter)
+ {
+ fprintf(stderr, "cups-browsed: "
+ "Could not allocate memory for LDAP browse query filter!\n");
+ BrowseLocalProtocols &= ~BROWSE_LDAP;
+ BrowseRemoteProtocols &= ~BROWSE_LDAP;
+
+ return FALSE;
+ }
+
+ if (BrowseLDAPFilter)
+ {
+ snprintf(tmpFilter, filterLen + 1, "(&%s%s)", LDAP_BROWSE_FILTER, BrowseLDAPFilter);
+ free(BrowseLDAPFilter);
+ BrowseLDAPFilter = NULL;
+ }
+ else
+ strcpy(tmpFilter, LDAP_BROWSE_FILTER);
+
+ BrowseLDAPFilter = tmpFilter;
+
+ /*
+ * Open LDAP handle...
+ */
+
+ BrowseLDAPHandle = ldap_connect();
+ }
+
+ cupsdUpdateLDAPBrowse();
+ recheck_timer();
+ }
+
+ /* Call a new timeout handler so that we run again */
+ g_timeout_add_seconds (BrowseInterval, browse_ldap_poll, data);
+
+ /* Stop this timeout handler, we called a new one */
+ return FALSE;
+}
+#endif /* HAVE_LDAP */
+
int
compare_pointers (void *a, void *b, void *data)
{
@@ -3051,6 +4534,8 @@ read_configuration (const char *filename)
protocols |= BROWSE_DNSSD;
else if (!strcasecmp(p, "cups"))
protocols |= BROWSE_CUPS;
+ else if (!strcasecmp(p, "ldap"))
+ protocols |= BROWSE_LDAP;
else if (strcasecmp(p, "none"))
debug_printf("cups-browsed: Unknown protocol '%s'\n", p);
@@ -3165,6 +4650,31 @@ read_configuration (const char *filename)
debug_printf("cups-browsed: Invalid auto shutdown timeout value: %d\n",
t);
}
+#ifdef HAVE_LDAP
+ else if (!strcasecmp(line, "BrowseLDAPBindDN") && value) {
+ if (value[0] != '\0')
+ BrowseLDAPBindDN = strdup(value);
+ }
+# ifdef HAVE_LDAP_SSL
+ else if (!strcasecmp(line, "BrowseLDAPCACertFile") && value) {
+ if (value[0] != '\0')
+ BrowseLDAPCACertFile = strdup(value);
+ }
+# endif /* HAVE_LDAP_SSL */
+ else if (!strcasecmp(line, "BrowseLDAPDN") && value) {
+ if (value[0] != '\0')
+ BrowseLDAPDN = strdup(value);
+ } else if (!strcasecmp(line, "BrowseLDAPPassword") && value) {
+ if (value[0] != '\0')
+ BrowseLDAPPassword = strdup(value);
+ } else if (!strcasecmp(line, "BrowseLDAPServer") && value) {
+ if (value[0] != '\0')
+ BrowseLDAPServer = strdup(value);
+ } else if (!strcasecmp(line, "BrowseLDAPFilter") && value) {
+ if (value[0] != '\0')
+ BrowseLDAPFilter = strdup(value);
+ }
+#endif /* HAVE_LDAP */
}
cupsFileClose(fp);
@@ -3223,7 +4733,8 @@ find_previous_queue (gpointer key,
else
p->timeout = time(NULL) + TIMEOUT_CONFIRM;
- p->duplicate = 0;
+ p->duplicate_of = NULL;
+ p->num_duplicates = 0;
debug_printf("cups-browsed: Found CUPS queue %s (URI: %s) from previous session.\n",
p->name, p->uri);
} else {
@@ -3240,6 +4751,9 @@ int main(int argc, char*argv[]) {
const char *val;
remote_printer_t *p;
GDBusProxy *proxy = NULL;
+ CupsNotifier *cups_notifier = NULL;
+ GError *error = NULL;
+ int subscription_id = 0;
/* Turn on debug mode if requested */
if (argc >= 2)
@@ -3334,6 +4848,11 @@ int main(int argc, char*argv[]) {
BrowseLocalProtocols &= ~BROWSE_DNSSD;
}
+ if (BrowseLocalProtocols & BROWSE_LDAP) {
+ fprintf(stderr, "Local support for LDAP not implemented\n");
+ BrowseLocalProtocols &= ~BROWSE_LDAP;
+ }
+
#ifndef HAVE_AVAHI
if (BrowseRemoteProtocols & BROWSE_DNSSD) {
fprintf(stderr, "Remote support for DNSSD not supported\n");
@@ -3341,6 +4860,13 @@ int main(int argc, char*argv[]) {
}
#endif /* HAVE_AVAHI */
+#ifndef HAVE_LDAP
+ if (BrowseRemoteProtocols & BROWSE_LDAP) {
+ fprintf(stderr, "Remote support for LDAP not supported\n");
+ BrowseRemoteProtocols &= ~BROWSE_LDAP;
+ }
+#endif /* HAVE_LDAP */
+
/* Wait for CUPS daemon to start */
while ((http = http_connect_local ()) == NULL)
sleep(1);
@@ -3357,6 +4883,8 @@ int main(int argc, char*argv[]) {
/* Read out the currently defined CUPS queues and find the ones which we
have added in an earlier session */
update_local_printers ();
+ if ((val = get_cups_default_printer()) != NULL)
+ default_printer = strdup(val);
remote_printers = cupsArrayNew((cups_array_func_t)compare_remote_printers,
NULL);
g_hash_table_foreach (local_printers, find_previous_queue, NULL);
@@ -3484,6 +5012,14 @@ int main(int argc, char*argv[]) {
g_idle_add (send_browse_data, NULL);
}
+#ifdef HAVE_LDAP
+ if (BrowseRemoteProtocols & BROWSE_LDAP) {
+ debug_printf ("cups-browsed: will browse poll LDAP every %ds\n",
+ BrowseInterval);
+ g_idle_add (browse_ldap_poll, NULL);
+ }
+#endif /* HAVE_LDAP */
+
if (BrowsePoll) {
size_t index;
for (index = 0;
@@ -3495,6 +5031,28 @@ int main(int argc, char*argv[]) {
}
}
+ /* Subscribe to CUPS' D-Bus notifications and create a proxy to receive
+ the notifications */
+ subscription_id = create_subscription ();
+ g_timeout_add_seconds (NOTIFY_LEASE_DURATION - 60,
+ renew_subscription_timeout,
+ &subscription_id);
+ cups_notifier = cups_notifier_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
+ 0,
+ NULL,
+ CUPS_DBUS_PATH,
+ NULL,
+ &error);
+ if (error) {
+ g_warning ("Error creating cups notify handler: %s", error->message);
+ g_error_free (error);
+ goto fail;
+ }
+ g_signal_connect (cups_notifier, "printer-state-changed",
+ G_CALLBACK (on_printer_state_changed), NULL);
+ g_signal_connect (cups_notifier, "printer-deleted",
+ G_CALLBACK (on_printer_deleted), NULL);
+
/* If auto shutdown is active and we do not find any printers initially,
schedule the shutdown in autoshutdown_timeout seconds */
if (autoshutdown && !autoshutdown_exec_id &&
@@ -3515,6 +5073,10 @@ fail:
/* Clean up things */
+ cancel_subscription (subscription_id);
+ if (cups_notifier)
+ g_object_unref (cups_notifier);
+
if (proxy)
g_object_unref (proxy);
@@ -3557,6 +5119,15 @@ fail:
avahi_shutdown();
#endif /* HAVE_AVAHI */
+#ifdef HAVE_LDAP
+ if (((BrowseLocalProtocols | BrowseRemoteProtocols) & BROWSE_LDAP) &&
+ BrowseLDAPHandle)
+ {
+ ldap_disconnect(BrowseLDAPHandle);
+ BrowseLDAPHandle = NULL;
+ }
+#endif /* HAVE_LDAP */
+
if (browsesocket != -1)
close (browsesocket);
diff --git a/utils/cups-browsed.conf.5 b/utils/cups-browsed.conf.5
index ebfc694ae..b5ffb8039 100644
--- a/utils/cups-browsed.conf.5
+++ b/utils/cups-browsed.conf.5
@@ -63,13 +63,14 @@ The default is "dnssd cups".
BrowseRemoteProtocols CUPS dnssd
BrowseRemoteProtocols CUPS
BrowseRemoteProtocols dnssd
+ BrowseRemoteProtocols ldap
.fam T
.fi
The BrowseProtocols directive specifies the protocols to use when
finding remote shared printers on the network and advertising local
-shared printers. "dnssd" is ignored for BrowseLocalProtocols. Multiple
-protocols can be specified by separating them with spaces. The
+shared printers. "dnssd" and "ldap" are ignored for BrowseLocalProtocols.
+Multiple protocols can be specified by separating them with spaces. The
default is "none" for BrowseLocalProtocols and "dnssd cups" for
BrowseRemoteProtocols.
.PP
@@ -79,6 +80,25 @@ BrowseRemoteProtocols.
BrowseProtocols CUPS dnssd
BrowseProtocols CUPS
BrowseProtocols dnssd
+ BrowseProtocols ldap
+
+.fam T
+.fi
+The configuration for the LDAP browsing mode define where the LDAP search
+should be performed. If built with an LDAP library that supports TLS, the
+path to the server's certificate, or to a certificates store, can be
+specified.
+The optional filter allows the LDAP search to be more specific, and is used
+in addition to the hardcoded filter (objectclass=cupsPrinter).
+.PP
+.nf
+.fam C
+ BrowseLDAPBindDN cn=cups-browsed,dc=domain,dc=tld
+ BrowseLDAPCACertFile /path/to/server/certificate.pem
+ BrowseLDAPDN ou=printers,dc=domain,dc=tld
+ BrowseLDAPFilter (printerLocation=/Office 1/*)
+ BrowseLDAPPassword s3cret
+ BrowseLDAPServer ldaps://ldap.domain.tld
.fam T
.fi
diff --git a/utils/cups-browsed.conf.in b/utils/cups-browsed.conf.in
index c1cfc44fa..f8deeab0d 100644
--- a/utils/cups-browsed.conf.in
+++ b/utils/cups-browsed.conf.in
@@ -1,5 +1,5 @@
# Which protocols will we use to discover printers on the network?
-# Can use DNSSD and/or CUPS, or 'none' for neither.
+# Can use DNSSD and/or CUPS and/or LDAP, or 'none' for neither.
BrowseRemoteProtocols @BROWSEREMOTEPROTOCOLS@
# Which protocols will we use to broadcast shared local printers to the network?
@@ -10,7 +10,7 @@ BrowseRemoteProtocols @BROWSEREMOTEPROTOCOLS@
# Settings of this directive apply to both BrowseRemoteProtocols and
# BrowseLocalProtocols.
-# Can use DNSSD and/or CUPS, or 'none' for neither.
+# Can use DNSSD and/or CUPS and/or LDAP, or 'none' for neither.
# BrowseProtocols none
# Only browse remote printers from selected servers
@@ -25,6 +25,15 @@ BrowseRemoteProtocols @BROWSEREMOTEPROTOCOLS@
# BrowsePoll cups.example.com:631
# BrowsePoll cups.example.com:631/version=1.1
+# LDAP browsing configuration
+# The default value for all options is an empty string. Example configuration:
+# BrowseLDAPBindDN cn=cups-browsed,dc=domain,dc=tld
+# BrowseLDAPCACertFile /path/to/server/certificate.pem
+# BrowseLDAPDN ou=printers,dc=domain,dc=tld
+# BrowseLDAPFilter (printerLocation=/Office 1/*)
+# BrowseLDAPPassword s3cret
+# BrowseLDAPServer ldaps://ldap.domain.tld
+
# Use DomainSocket to access the local CUPS daemon via another than the
# default domain socket
# DomainSocket @CUPS_DEFAULT_DOMAINSOCKET@
diff --git a/utils/org.cups.cupsd.Notifier.xml b/utils/org.cups.cupsd.Notifier.xml
new file mode 100644
index 000000000..e70a5c31d
--- /dev/null
+++ b/utils/org.cups.cupsd.Notifier.xml
@@ -0,0 +1,147 @@
+<node>
+
+ <interface name="org.cups.cupsd.Notifier">
+
+ <signal name="ServerStarted">
+ <arg type="s" name="text" />
+ </signal>
+
+ <signal name="ServerRestarted">
+ <arg type="s" name="text" />
+ </signal>
+
+ <signal name="ServerStopped">
+ <arg type="s" name="text" />
+ </signal>
+
+ <signal name="ServerAudit">
+ <arg type="s" name="text" />
+ </signal>
+
+ <signal name="PrinterAdded">
+ <arg type="s" name="text" />
+ <arg type="s" name="printer_uri" />
+ <arg type="s" name="printer_name" />
+ <arg type="u" name="printer_state" />
+ <arg type="s" name="printer_state_reasons" />
+ <arg type="b" name="printer_is_accepting_jobs" />
+ </signal>
+
+ <signal name="PrinterDeleted">
+ <arg type="s" name="text" />
+ <arg type="s" name="printer_uri" />
+ <arg type="s" name="printer_name" />
+ <arg type="u" name="printer_state" />
+ <arg type="s" name="printer_state_reasons" />
+ <arg type="b" name="printer_is_accepting_jobs" />
+ </signal>
+
+ <signal name="PrinterModified">
+ <arg type="s" name="text" />
+ <arg type="s" name="printer_uri" />
+ <arg type="s" name="printer_name" />
+ <arg type="u" name="printer_state" />
+ <arg type="s" name="printer_state_reasons" />
+ <arg type="b" name="printer_is_accepting_jobs" />
+ </signal>
+
+ <signal name="PrinterRestarted">
+ <arg type="s" name="text" />
+ <arg type="s" name="printer_uri" />
+ <arg type="s" name="printer_name" />
+ <arg type="u" name="printer_state" />
+ <arg type="s" name="printer_state_reasons" />
+ <arg type="b" name="printer_is_accepting_jobs" />
+ </signal>
+
+ <signal name="PrinterStopped">
+ <arg type="s" name="text" />
+ <arg type="s" name="printer_uri" />
+ <arg type="s" name="printer_name" />
+ <arg type="u" name="printer_state" />
+ <arg type="s" name="printer_state_reasons" />
+ <arg type="b" name="printer_is_accepting_jobs" />
+ </signal>
+
+ <signal name="PrinterShutdown">
+ <arg type="s" name="text" />
+ <arg type="s" name="printer_uri" />
+ <arg type="s" name="printer_name" />
+ <arg type="u" name="printer_state" />
+ <arg type="s" name="printer_state_reasons" />
+ <arg type="b" name="printer_is_accepting_jobs" />
+ </signal>
+
+ <signal name="PrinterStateChanged">
+ <arg type="s" name="text" />
+ <arg type="s" name="printer_uri" />
+ <arg type="s" name="printer_name" />
+ <arg type="u" name="printer_state" />
+ <arg type="s" name="printer_state_reasons" />
+ <arg type="b" name="printer_is_accepting_jobs" />
+ </signal>
+
+ <signal name="PrinterFinishingsChanged">
+ <arg type="s" name="text" />
+ <arg type="s" name="printer_uri" />
+ <arg type="s" name="printer_name" />
+ <arg type="u" name="printer_state" />
+ <arg type="s" name="printer_state_reasons" />
+ <arg type="b" name="printer_is_accepting_jobs" />
+ </signal>
+
+ <signal name="PrinterMediaChanged">
+ <arg type="s" name="text" />
+ <arg type="s" name="printer_uri" />
+ <arg type="s" name="printer_name" />
+ <arg type="u" name="printer_state" />
+ <arg type="s" name="printer_state_reasons" />
+ <arg type="b" name="printer_is_accepting_jobs" />
+ </signal>
+
+ <signal name="JobCreated">
+ <arg type="s" name="text" />
+ <arg type="s" name="printer_uri" />
+ <arg type="s" name="printer_name" />
+ <arg type="u" name="printer_state" />
+ <arg type="s" name="printer_state_reasons" />
+ <arg type="b" name="printer_is_accepting_jobs" />
+ <arg type="u" name="job_id" />
+ <arg type="u" name="job_state" />
+ <arg type="s" name="job_state_reasons" />
+ <arg type="s" name="job_name" />
+ <arg type="u" name="job_impressions_completed" />
+ </signal>
+
+ <signal name="JobCompleted">
+ <arg type="s" name="text" />
+ <arg type="s" name="printer_uri" />
+ <arg type="s" name="printer_name" />
+ <arg type="u" name="printer_state" />
+ <arg type="s" name="printer_state_reasons" />
+ <arg type="b" name="printer_is_accepting_jobs" />
+ <arg type="u" name="job_id" />
+ <arg type="u" name="job_state" />
+ <arg type="s" name="job_state_reasons" />
+ <arg type="s" name="job_name" />
+ <arg type="u" name="job_impressions_completed" />
+ </signal>
+
+ <signal name="JobState">
+ <arg type="s" name="text" />
+ <arg type="s" name="printer_uri" />
+ <arg type="s" name="printer_name" />
+ <arg type="u" name="printer_state" />
+ <arg type="s" name="printer_state_reasons" />
+ <arg type="b" name="printer_is_accepting_jobs" />
+ <arg type="u" name="job_id" />
+ <arg type="u" name="job_state" />
+ <arg type="s" name="job_state_reasons" />
+ <arg type="s" name="job_name" />
+ <arg type="u" name="job_impressions_completed" />
+ </signal>
+
+ </interface>
+
+</node>
+