diff options
author | Didier Raboud <odyx@debian.org> | 2015-08-19 18:03:33 +0200 |
---|---|---|
committer | Didier Raboud <odyx@debian.org> | 2015-08-18 19:56:55 +0200 |
commit | 42ed110d6642370105cb6c3a7e8328012395cab4 (patch) | |
tree | a90d25f041d4b5142744f3a83c4994d464afd5fa | |
parent | 6d72268775295f02fa162f451dad6551ec868a18 (diff) |
Imported Upstream version 1.0.73
41 files changed, 2855 insertions, 162 deletions
@@ -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 *~ @@ -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 @@ -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 @@ -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> + |