diff --git a/.cups-filters.metadata b/.cups-filters.metadata index a5a761e..8005771 100644 --- a/.cups-filters.metadata +++ b/.cups-filters.metadata @@ -1 +1,4 @@ +e6ba7481d0e71b965d4c3b63dbfb8b489a87ca2f SOURCES/backend.tar.gz 969e4efc14a33816f3d81a4afd3b5b0d52a6f769 SOURCES/cups-filters-1.0.35.tar.xz +8073f56a227f3bc0f9f5348030e8c852657be733 SOURCES/m4.tar.gz +031a9f1d7a4e4ba870f70a3e57ffd4cc39fb421d SOURCES/utils.tar.gz diff --git a/.gitignore b/.gitignore index 799e547..01c6229 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,4 @@ +SOURCES/backend.tar.gz SOURCES/cups-filters-1.0.35.tar.xz +SOURCES/m4.tar.gz +SOURCES/utils.tar.gz diff --git a/SOURCES/0001-Fixing-covscan-issues.patch b/SOURCES/0001-Fixing-covscan-issues.patch new file mode 100644 index 0000000..0d3b982 --- /dev/null +++ b/SOURCES/0001-Fixing-covscan-issues.patch @@ -0,0 +1,136 @@ +diff -up cups-filters-1.0.35/utils/cups-browsed.c.covscan cups-filters-1.0.35/utils/cups-browsed.c +--- cups-filters-1.0.35/utils/cups-browsed.c.covscan 2019-02-27 17:52:37.000000000 +0100 ++++ cups-filters-1.0.35/utils/cups-browsed.c 2019-03-18 16:01:49.345858931 +0100 +@@ -1934,7 +1934,10 @@ is_disabled(const char *printer, const c + pstate = (ipp_pstate_t)ippGetInteger(attr, 0); + else if (!strcmp(ippGetName(attr), "printer-state-message") && + ippGetValueTag(attr) == IPP_TAG_TEXT) { +- free(pstatemsg); ++ if (pstatemsg != NULL) { ++ free(pstatemsg); ++ pstatemsg = NULL; ++ } + p = ippGetString(attr, 0, NULL); + if (p != NULL) pstatemsg = strdup(p); + } +@@ -1951,16 +1954,22 @@ is_disabled(const char *printer, const c + case IPP_PRINTER_IDLE: + case IPP_PRINTER_PROCESSING: + ippDelete(response); +- free(pstatemsg); ++ if (pstatemsg != NULL) { ++ free(pstatemsg); ++ pstatemsg = NULL; ++ } + return NULL; + case IPP_PRINTER_STOPPED: + ippDelete(response); + if (reason == NULL) + return pstatemsg; +- else if (strcasestr(pstatemsg, reason) != NULL) ++ else if (pstatemsg != NULL && (strcasestr(pstatemsg, reason) != NULL)) + return pstatemsg; + else { +- free(pstatemsg); ++ if (pstatemsg != NULL) { ++ free(pstatemsg); ++ pstatemsg = NULL; ++ } + return NULL; + } + } +@@ -1969,12 +1978,18 @@ is_disabled(const char *printer, const c + debug_printf("No information regarding enabled/disabled found about the requested printer '%s'\n", + printer); + ippDelete(response); +- free(pstatemsg); ++ if (pstatemsg != NULL) { ++ free(pstatemsg); ++ pstatemsg = NULL; ++ } + return NULL; + } + debug_printf("ERROR: Request for printer info failed: %s\n", + cupsLastErrorString()); +- free(pstatemsg); ++ if (pstatemsg != NULL) { ++ free(pstatemsg); ++ pstatemsg = NULL; ++ } + return NULL; + } + +@@ -3421,6 +3436,8 @@ gboolean handle_cups_queues(gpointer unu + } else { + /* Device URI: ipp(s)://:631/printers/ */ + strncpy(device_uri, p->uri, sizeof(device_uri)); ++ if (strlen(p->uri) > HTTP_MAX_URI-1) ++ device_uri[HTTP_MAX_URI-1] = '\0'; + debug_printf("Print queue %s is for an IPP network printer, or we do not get notifications from CUPS, using direct device URI %s\n", + p->name, device_uri); + } +@@ -3529,6 +3546,8 @@ gboolean handle_cups_queues(gpointer unu + } else if (!strncmp(line, "*Default", 8)) { + cont_line_read = 0; + strncpy(keyword, line + 8, sizeof(keyword)); ++ if ((strlen(line) + 8) > 1023) ++ keyword[1023] = '\0'; + for (keyptr = keyword; *keyptr; keyptr ++) + if (*keyptr == ':' || isspace(*keyptr & 255)) + break; +@@ -5871,7 +5890,7 @@ read_configuration (const char *filename + in the configuration file is used. */ + while ((i < cupsArrayCount(command_line_config) && + (value = cupsArrayIndex(command_line_config, i++)) && +- strncpy(line, value, sizeof(line))) || ++ strncpy(line, value, sizeof(line)) && ((strlen(value) > HTTP_MAX_BUFFER-1)? line[HTTP_MAX_BUFFER-1] = '\0': 1)) || + cupsFileGetConf(fp, line, sizeof(line), &value, &linenum)) { + if (linenum < 0) { + /* We are still reading options from the command line ("-o ..."), +@@ -6098,6 +6117,7 @@ read_configuration (const char *filename + if (filter->cregexp) + regfree(filter->cregexp); + free(filter); ++ filter = NULL; + } + } else if ((!strcasecmp(line, "BrowseInterval") || !strcasecmp(line, "BrowseTimeout")) && value) { + int t = atoi(value); +@@ -6113,7 +6133,7 @@ read_configuration (const char *filename + debug_printf("Invalid %s value: %d\n", + line, t); + } else if (!strcasecmp(line, "DomainSocket") && value) { +- if (value[0] != '\0') ++ if (DomainSocket == NULL && value[0] != '\0') + DomainSocket = strdup(value); + } else if ((!strcasecmp(line, "HttpLocalTimeout") || !strcasecmp(line, "HttpRemoteTimeout")) && value) { + int t = atoi(value); +@@ -6168,7 +6188,7 @@ read_configuration (const char *filename + else if (!strncasecmp(value, "QueueOnServers", 14)) + LoadBalancingType = QUEUE_ON_SERVERS; + } else if (!strcasecmp(line, "DefaultOptions") && value) { +- if (strlen(value) > 0) ++ if (DefaultOptions == NULL && strlen(value) > 0) + DefaultOptions = strdup(value); + } else if (!strcasecmp(line, "AutoShutdown") && value) { + char *p, *saveptr; +@@ -6537,6 +6557,8 @@ int main(int argc, char*argv[]) { + daemon, not with remote ones. */ + if (getenv("CUPS_SERVER") != NULL) { + strncpy(local_server_str, getenv("CUPS_SERVER"), sizeof(local_server_str)); ++ if (strlen(getenv("CUPS_SERVER")) > 1023) ++ local_server_str[1023] = '\0'; + } else { + #ifdef CUPS_DEFAULT_DOMAINSOCKET + if (DomainSocket == NULL) +@@ -6876,6 +6898,11 @@ fail: + /* Close log file if we have one */ + if (debug_logfile == 1) + stop_debug_logging(); ++ ++ if (DefaultOptions != NULL) ++ free(DefaultOptions); ++ if (DomainSocket != NULL) ++ free(DomainSocket); + + return ret; + diff --git a/SOURCES/0001-cups-browsed-Fixed-freeing-of-literal-string-caused-.patch b/SOURCES/0001-cups-browsed-Fixed-freeing-of-literal-string-caused-.patch new file mode 100644 index 0000000..6c2bf22 --- /dev/null +++ b/SOURCES/0001-cups-browsed-Fixed-freeing-of-literal-string-caused-.patch @@ -0,0 +1,26 @@ +diff --git a/utils/cups-browsed.c b/utils/cups-browsed.c +index 9f6f25b7..7c3f5c2b 100644 +--- a/utils/cups-browsed.c ++++ b/utils/cups-browsed.c +@@ -7889,8 +7889,11 @@ read_configuration (const char *filename) + debug_printf("Invalid %s value: %d\n", + line, t); + } else if (!strcasecmp(line, "DomainSocket") && value) { +- if (DomainSocket == NULL && value[0] != '\0') ++ if (value[0] != '\0') { ++ if (DomainSocket != NULL) ++ free(DomainSocket); + DomainSocket = strdup(value); ++ } + } else if ((!strcasecmp(line, "HttpLocalTimeout") || !strcasecmp(line, "HttpRemoteTimeout")) && value) { + int t = atoi(value); + if (t >= 0) { +@@ -8466,7 +8469,7 @@ int main(int argc, char*argv[]) { + } else { + #ifdef CUPS_DEFAULT_DOMAINSOCKET + if (DomainSocket == NULL) +- DomainSocket = CUPS_DEFAULT_DOMAINSOCKET; ++ DomainSocket = strdup(CUPS_DEFAULT_DOMAINSOCKET); + #endif + if (DomainSocket != NULL) { + struct stat sockinfo; /* Domain socket information */ diff --git a/SOURCES/Makefile.am b/SOURCES/Makefile.am new file mode 100644 index 0000000..c51d452 --- /dev/null +++ b/SOURCES/Makefile.am @@ -0,0 +1,735 @@ +ACLOCAL_AMFLAGS = -I m4 + +pkgconfdir = $(libdir)/pkgconfig +pkgconf_DATA = \ + libcupsfilters.pc \ + libfontembed.pc + +doc_DATA = \ + AUTHORS \ + COPYING \ + NEWS \ + INSTALL \ + README + +EXTRA_DIST = \ + $(doc_DATA) \ + autogen.sh \ + libcupsfilters.pc.in \ + libfontembed.pc.in \ + utils/cups-browsed.service + +# ======== +# Backends +# ======== +pkgbackenddir = $(CUPS_SERVERBIN)/backend +pkgbackend_PROGRAMS = parallel serial implicitclass + +check_PROGRAMS = test1284 +# We need ieee1284 up and running. +# Leave it to the user to run if they have the bus. +#TESTS = test1284 + +parallel_SOURCES = \ + backend/backend-private.h \ + backend/ieee1284.c \ + backend/parallel.c +parallel_LDADD = $(CUPS_LIBS) +parallel_CFLAGS = $(CUPS_CFLAGS) + +serial_SOURCES = \ + backend/backend-private.h \ + backend/serial.c +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 \ + backend/test1284.c +test1284_LDADD = $(CUPS_LIBS) +test1284_CFLAGS = $(CUPS_CFLAGS) + +# ======= +# Banners +# ======= +pkgbannerdir = $(CUPS_DATADIR)/banners +pkgbanner_DATA = \ + banners/classified \ + banners/confidential \ + banners/secret \ + banners/standard \ + banners/topsecret \ + banners/unclassified + +EXTRA_DIST += $(pkgbanner_DATA) + +# ======== +# Charsets +# ======== +pkgcharsetdir = $(CUPS_DATADIR)/charsets +pkgcharset_DATA = \ + charset/pdf.utf-8.heavy \ + charset/pdf.utf-8.simple + +EXTRA_DIST += $(pkgcharset_DATA) + +# ==================== +# CUPS Filters library +# ==================== +pkgfiltersincludedir = $(includedir)/cupsfilters +pkgfiltersinclude_DATA = \ + cupsfilters/driver.h \ + cupsfilters/image.h + +lib_LTLIBRARIES = libcupsfilters.la + +check_PROGRAMS += \ + testcmyk \ + testdither \ + testimage \ + testrgb +TESTS = \ + testdither +# testcmyk # fails as it opens some image.ppm which is nowerhe to be found. +# testimage # requires also some ppm file as argument +# testrgb # same error +# FIXME: run old testdither +# ./testdither > test/0-255.pgm 2>test/0-255.log +# ./testdither 0 127 255 > test/0-127-255.pgm 2>test/0-127-255.log +# ./testdither 0 85 170 255 > test/0-85-170-255.pgm 2>test/0-85-170-255.log +# ./testdither 0 63 127 170 198 227 255 > test/0-63-127-170-198-227-255.pgm 2>test/0-63-127-170-198-227-255.log +# ./testdither 0 210 383 > test/0-210-383.pgm 2>test/0-210-383.log +# ./testdither 0 82 255 > test/0-82-255.pgm 2>test/0-82-255.log +# ./testdither 0 510 > test/0-510.pgm 2>test/0-510.log +# ./testdither 0 1020 > test/0-1020.pgm 2>test/0-1020.log + + +libcupsfilters_la_SOURCES = \ + cupsfilters/attr.c \ + cupsfilters/check.c \ + cupsfilters/cmyk.c \ + cupsfilters/dither.c \ + cupsfilters/image.c \ + cupsfilters/image-bmp.c \ + cupsfilters/image-colorspace.c \ + cupsfilters/image-gif.c \ + cupsfilters/image-jpeg.c \ + cupsfilters/image-photocd.c \ + cupsfilters/image-pix.c \ + cupsfilters/image-png.c \ + cupsfilters/image-pnm.c \ + cupsfilters/image-private.h \ + cupsfilters/image-sgi.c \ + cupsfilters/image-sgi.h \ + cupsfilters/image-sgilib.c \ + cupsfilters/image-sun.c \ + cupsfilters/image-tiff.c \ + cupsfilters/image-zoom.c \ + cupsfilters/lut.c \ + cupsfilters/pack.c \ + cupsfilters/rgb.c \ + cupsfilters/srgb.c \ + $(pkgfiltersinclude_DATA) +libcupsfilters_la_LIBADD = \ + $(CUPS_LIBS) \ + $(LIBJPEG_LIBS) \ + $(LIBPNG_LIBS) \ + $(TIFF_LIBS) \ + -lm +libcupsfilters_la_CFLAGS = \ + $(CUPS_CFLAGS) \ + $(LIBJPEG_CFLAGS) \ + $(LIBPNG_CFLAGS) \ + $(TIFF_CFLAGS) + +libcupsfilters_la_LDFLAGS = \ + -no-undefined \ + -version-info 1 + +testcmyk_SOURCES = \ + cupsfilters/testcmyk.c \ + $(pkgfiltersinclude_DATA) +testcmyk_LDADD = \ + libcupsfilters.la \ + -lm + +testdither_SOURCES = \ + cupsfilters/testdither.c \ + $(pkgfiltersinclude_DATA) +testdither_LDADD = \ + libcupsfilters.la \ + -lm + +testimage_SOURCES = \ + cupsfilters/testimage.c \ + $(pkgfiltersinclude_DATA) +testimage_LDADD = \ + $(LIBJPEG_LIBS) \ + $(LIBPNG_LIBS) \ + $(TIFF_LIBS) \ + libcupsfilters.la \ + -lm +testimage_CFLAGS = \ + $(LIBJPEG_CFLAGS) \ + $(LIBPNG_CFLAGS) \ + $(TIFF_CFLAGS) + +testrgb_SOURCES = \ + cupsfilters/testrgb.c \ + $(pkgfiltersinclude_DATA) +testrgb_LDADD = \ + libcupsfilters.la \ + -lm + +EXTRA_DIST += \ + $(pkgfiltersinclude_DATA) \ + cupsfilters/image.pgm \ + cupsfilters/image.ppm + +# ========= +# CUPS Data +# ========= +pkgcupsdatadir = $(CUPS_DATADIR)/data +pkgcupsdata_DATA = \ + data/default.pdf \ + data/default-testpage.pdf \ + data/testprint + +EXTRA_DIST += $(pkgcupsdata_DATA) + +# =========== +# CUPS Config +# =========== +pkgcupsserverrootdir = $(CUPS_SERVERROOT) +pkgcupsserverroot_DATA = \ + utils/cups-browsed.conf + +# ======= +# Drivers +# ======= +pkgdriverdir = $(CUPS_DATADIR)/drv +pkgdriver_DATA = \ + drv/cupsfilters.drv + +EXTRA_DIST += $(pkgdriver_DATA) + +# ======= +# Definitions for drivers +# ======= +pkgppdcdir = $(CUPS_DATADIR)/ppdc +pkgppdc_DATA = \ + filter/pcl.h + +EXTRA_DIST += $(pkgppdc_DATA) + +# ===== +# MIMEs +# ===== +pkgmimedir = $(CUPS_DATADIR)/mime +pkgmime_DATA = \ + mime/cupsfilters.convs \ + mime/cupsfilters.types + +EXTRA_DIST += $(pkgmime_DATA) + +# ================= +# Fontembed library +# ================= +pkgfontembedincludedir = $(includedir)/fontembed +pkgfontembedinclude_DATA = \ + fontembed/bitset.h \ + fontembed/embed.h \ + fontembed/fontfile.h \ + fontembed/iofn.h \ + fontembed/sfnt.h + +lib_LTLIBRARIES += libfontembed.la + +bin_PROGRAMS = ttfread + +check_PROGRAMS += \ + test_analyze \ + test_pdf \ + test_ps +TESTS += \ + test_analyze \ + test_pdf \ + test_ps + +libfontembed_la_SOURCES = \ + fontembed/aglfn13.c \ + fontembed/bitset.h \ + fontembed/dynstring.c \ + fontembed/dynstring.h \ + fontembed/embed.c \ + fontembed/embed.h \ + fontembed/embed_sfnt.c \ + fontembed/embed_sfnt_int.h \ + fontembed/embed_pdf.c \ + fontembed/embed_pdf.h \ + fontembed/embed_pdf_int.h \ + fontembed/fontfile.c \ + fontembed/fontfile.h \ + fontembed/frequent.c \ + fontembed/frequent.h \ + fontembed/iofn.h \ + fontembed/macroman.h \ + fontembed/sfnt.c \ + fontembed/sfnt.h \ + fontembed/sfnt_int.h \ + fontembed/sfnt_subset.c +libfontembed_la_LDFLAGS = \ + -no-undefined \ + -version-info 1 + +ttfread_SOURCES = fontembed/main.c +ttfread_LDADD = libfontembed.la + +test_analyze_SOURCES = fontembed/test_analyze.c +test_analyze_LDADD = libfontembed.la + +test_pdf_SOURCES = fontembed/test_pdf.c +test_pdf_LDADD = libfontembed.la + +test_ps_SOURCES = fontembed/test_ps.c +test_ps_LDADD = libfontembed.la + +EXTRA_DIST += \ + $(pkgfontembedinclude_DATA) \ + fontembed/README + +# =========== +# PDF to OPVP +# =========== +pkgfilterdir = $(CUPS_SERVERBIN)/filter +pkgfilter_PROGRAMS = pdftoopvp + +pkgfontconfigdir = $(sysconfdir)/$(FONTDIR) +pkgfontconfig_DATA = filter/pdftoopvp/99pdftoopvp.conf + +pdftoopvp_SOURCES = \ + filter/pdftoopvp/oprs/OPRS.cxx \ + filter/pdftoopvp/oprs/OPRS.h \ + filter/pdftoopvp/oprs/OPVPSplashClip.cxx \ + filter/pdftoopvp/oprs/OPVPSplashClip.h \ + filter/pdftoopvp/oprs/OPVPSplash.cxx \ + filter/pdftoopvp/oprs/OPVPSplash.h \ + filter/pdftoopvp/oprs/OPVPSplashPath.cxx \ + filter/pdftoopvp/oprs/OPVPSplashPath.h \ + filter/pdftoopvp/oprs/OPVPSplashState.cxx \ + filter/pdftoopvp/oprs/OPVPSplashState.h \ + filter/pdftoopvp/oprs/OPVPSplashXPath.cxx \ + filter/pdftoopvp/oprs/OPVPSplashXPath.h \ + filter/pdftoopvp/oprs/OPVPWrapper.cxx \ + filter/pdftoopvp/oprs/OPVPWrapper.h \ + filter/pdftoopvp/oprs/OPVPWrapper_0_2.cxx \ + filter/pdftoopvp/oprs/OPVPWrapper_0_2.h \ + filter/pdftoopvp/OPVPError.h \ + filter/pdftoopvp/opvp/opvp_common.h \ + filter/pdftoopvp/opvp/opvp.h \ + filter/pdftoopvp/opvp/opvp_0_2_0.h \ + filter/pdftoopvp/OPVPOutputDev.cxx \ + filter/pdftoopvp/OPVPOutputDev.h \ + filter/pdftoopvp/pdftoopvp.cxx +pdftoopvp_CFLAGS = \ + $(CUPS_CFLAGS) \ + $(FREETYPE_CFLAGS) \ + $(FONTCONFIG_CFLAGS) \ + $(LIBPNG_CFLAGS) \ + $(POPPLER_CFLAGS) \ + -I$(srcdir)/filter/pdftoopvp/oprs \ + -I$(srcdir)/filter/pdftoopvp/opvp +pdftoopvp_CXXFLAGS = $(pdftoopvp_CFLAGS) +pdftoopvp_LDADD = \ + $(CUPS_LIBS) \ + $(FREETYPE_LIBS) \ + $(FONTCONFIG_LIBS) \ + $(LIBPNG_LIBS) \ + $(POPPLER_LIBS) \ + $(DLOPEN_LIBS) + +EXTRA_DIST += $(pkgfontconfig_DATA) + +# ========== +# PDF to PDF +# ========== +pkgfilter_PROGRAMS += pdftopdf + +pdftopdf_SOURCES = \ + filter/pdftopdf/pdftopdf.cc \ + filter/pdftopdf/pdftopdf_jcl.cc \ + filter/pdftopdf/pdftopdf_jcl.h \ + filter/pdftopdf/pdftopdf_processor.cc \ + filter/pdftopdf/pdftopdf_processor.h \ + filter/pdftopdf/qpdf_pdftopdf_processor.cc \ + filter/pdftopdf/qpdf_pdftopdf_processor.h \ + filter/pdftopdf/pptypes.cc \ + filter/pdftopdf/pptypes.h \ + filter/pdftopdf/nup.cc \ + filter/pdftopdf/nup.h \ + filter/pdftopdf/intervalset.cc \ + filter/pdftopdf/intervalset.h \ + filter/pdftopdf/qpdf_tools.cc \ + filter/pdftopdf/qpdf_tools.h \ + filter/pdftopdf/qpdf_xobject.cc \ + filter/pdftopdf/qpdf_xobject.h \ + filter/pdftopdf/qpdf_pdftopdf.cc \ + filter/pdftopdf/qpdf_pdftopdf.h \ + filter/pdftopdf/qpdf_cm.cc \ + filter/pdftopdf/qpdf_cm.h +pdftopdf_CFLAGS = \ + $(LIBQPDF_CFLAGS) \ + $(CUPS_CFLAGS) +pdftopdf_CXXFLAGS = -std=c++0x $(pdftopdf_CFLAGS) # -std=c++11 +pdftopdf_LDADD = \ + $(LIBQPDF_LIBS) \ + $(CUPS_LIBS) + +# ====================== +# Simple filter binaries +# ====================== +pkgfilter_SCRIPTS = \ + filter/imagetops \ + filter/pstopdf \ + filter/textonly \ + filter/texttops +pkgfilter_PROGRAMS += \ + bannertopdf \ + commandtoescpx \ + commandtopclx \ + pdftoijs \ + pdftops \ + pdftoraster \ + rastertoescpx \ + rastertopclx \ + texttopdf \ + urftopdf +if ENABLE_IMAGEFILTERS +pkgfilter_PROGRAMS += \ + imagetopdf \ + imagetoraster +endif + +check_PROGRAMS += \ + test_pdf1 \ + test_pdf2 + +TESTS += \ + test_pdf1 \ + test_pdf2 + +bannertopdf_SOURCES = \ + filter/banner.c \ + filter/banner.h \ + filter/bannertopdf.c \ + filter/pdf.cxx \ + filter/pdf.h +EXTRA_bannertopdf_SOURCES = filter/getline.c +bannertopdf_CFLAGS = \ + $(CUPS_CFLAGS) \ + $(LIBJPEG_CFLAGS) \ + $(LIBPNG_CFLAGS) \ + $(POPPLER_CFLAGS) \ + $(TIFF_CFLAGS) +bannertopdf_CXXFLAGS = $(bannertopdf_CFLAGS) +bannertopdf_LDADD = \ + $(GETLINE) \ + $(CUPS_LIBS) \ + $(LIBJPEG_LIBS) \ + $(LIBPNG_LIBS) \ + $(POPPLER_LIBS) \ + $(TIFF_LIBS) +bannertopdf_DEPENDENCIES = $(GETLINE) + +commandtoescpx_SOURCES = \ + cupsfilters/driver.h \ + filter/commandtoescpx.c \ + filter/pcl.h +commandtoescpx_CFLAGS= \ + $(CUPS_CFLAGS) \ + -I$(srcdir)/cupsfilters/ +commandtoescpx_LDADD = $(CUPS_LIBS) + +commandtopclx_SOURCES = \ + cupsfilters/driver.h \ + filter/commandtopclx.c \ + filter/pcl.h +commandtopclx_CFLAGS = \ + $(CUPS_CFLAGS) \ + -I$(srcdir)/cupsfilters/ +commandtopclx_LDADD = $(CUPS_LIBS) + +imagetopdf_SOURCES = \ + cupsfilters/image.h \ + filter/common.c \ + filter/common.h \ + filter/imagetopdf.c +imagetopdf_CFLAGS = \ + $(CUPS_CFLAGS) \ + $(LIBJPEG_CFLAGS) \ + $(LIBPNG_CFLAGS) \ + $(TIFF_CFLAGS) \ + -I$(srcdir)/cupsfilters/ +imagetopdf_LDADD = \ + $(CUPS_LIBS) \ + $(LIBJPEG_LIBS) \ + $(LIBPNG_LIBS) \ + $(TIFF_LIBS) \ + libcupsfilters.la + +imagetoraster_SOURCES = \ + cupsfilters/image.h \ + cupsfilters/image-private.h \ + filter/common.c \ + filter/common.h \ + filter/imagetoraster.c +imagetoraster_CFLAGS = \ + $(CUPS_CFLAGS) \ + -I$(srcdir)/cupsfilters/ +imagetoraster_LDADD = \ + $(CUPS_LIBS) \ + libcupsfilters.la + +urftopdf_SOURCES = \ + filter/urftopdf.cpp \ + filter/unirast.h +urftopdf_CXXFLAGS = \ + $(LIBQPDF_CFLAGS) +urftopdf_LDADD = \ + $(LIBQPDF_LIBS) + +pdftoijs_SOURCES = \ + filter/pdftoijs.cxx \ + filter/PDFError.h +pdftoijs_CFLAGS = \ + $(CUPS_CFLAGS) \ + $(IJS_CFLAGS) \ + $(POPPLER_CFLAGS) +pdftoijs_CXXFLAGS = $(pdftoijs_CFLAGS) +pdftoijs_LDADD = \ + $(CUPS_LIBS) \ + $(IJS_LIBS) \ + $(POPPLER_LIBS) + +pdftops_SOURCES = \ + filter/common.c \ + filter/common.h \ + filter/pdftops.c +EXTRA_pdftops_SOURCES = filter/strcasestr.c +pdftops_CFLAGS = $(CUPS_CFLAGS) +pdftops_LDADD = $(STRCASESTR) $(CUPS_LIBS) +pdftops_DEPENDENCIES = $(STRCASESTR) + +pdftoraster_SOURCES = \ + filter/pdftoraster.cxx \ + filter/PDFError.h +pdftoraster_CFLAGS = \ + $(CUPS_CFLAGS) \ + $(LCMS_CFLAGS) \ + $(LIBJPEG_CFLAGS) \ + $(LIBPNG_CFLAGS) \ + $(POPPLER_CFLAGS) \ + $(TIFF_CFLAGS) \ + -I$(srcdir)/cupsfilters/ +pdftoraster_CXXFLAGS = $(pdftoraster_CFLAGS) +pdftoraster_LDADD = \ + $(CUPS_LIBS) \ + $(LCMS_LIBS) \ + $(LIBJPEG_LIBS) \ + $(LIBPNG_LIBS) \ + $(POPPLER_LIBS) \ + $(TIFF_LIBS) \ + libcupsfilters.la + +rastertoescpx_SOURCES = \ + cupsfilters/driver.h \ + filter/escp.h \ + filter/rastertoescpx.c +rastertoescpx_CFLAGS = \ + $(CUPS_CFLAGS) \ + -I$(srcdir)/cupsfilters/ +rastertoescpx_LDADD = \ + $(CUPS_LIBS) \ + libcupsfilters.la + +rastertopclx_SOURCES = \ + cupsfilters/driver.h \ + filter/pcl.h \ + filter/pcl-common.c \ + filter/pcl-common.h \ + filter/rastertopclx.c +rastertopclx_CFLAGS = \ + $(CUPS_CFLAGS) \ + $(LIBPNG_CFLAGS) \ + -I$(srcdir)/cupsfilters/ +rastertopclx_LDADD = \ + $(CUPS_LIBS) \ + $(LIBPNG_LIBS) \ + libcupsfilters.la + +test_pdf1_SOURCES = \ + filter/pdfutils.c \ + filter/pdfutils.h \ + filter/test_pdf1.c \ + fontembed/embed.h \ + fontembed/sfnt.h +test_pdf1_CFLAGS = -I$(srcdir)/fontembed/ +test_pdf1_LDADD = libfontembed.la + +test_pdf2_SOURCES = \ + filter/pdfutils.c \ + filter/pdfutils.h \ + filter/test_pdf2.c \ + fontembed/embed.h \ + fontembed/sfnt.h +test_pdf2_CFLAGS = -I$(srcdir)/fontembed/ +test_pdf2_LDADD = libfontembed.la + +texttopdf_SOURCES = \ + filter/common.c \ + filter/common.h \ + filter/pdfutils.c \ + filter/pdfutils.h \ + filter/textcommon.c \ + filter/textcommon.h \ + filter/texttopdf.c \ + fontembed/bitset.h \ + fontembed/embed.h \ + fontembed/fontfile.h \ + fontembed/iofn.h \ + fontembed/sfnt.h +texttopdf_CFLAGS = \ + $(CUPS_CFLAGS) \ + $(FONTCONFIG_CFLAGS) \ + -I$(srcdir)/fontembed/ +texttopdf_LDADD = \ + $(CUPS_LIBS) \ + $(FONTCONFIG_LIBS) \ + libfontembed.la + +# Not reliable bash script +#TESTS += filter/test.sh + +EXTRA_DIST += \ + $(pkgfilter_SCRIPTS) \ + filter/test.sh + +# ===== +# 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 \ + utils/org.cups.cupsd.Notifier.xml + +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) \ + $(GLIB_CFLAGS) \ + $(GIO_CFLAGS) \ + $(GIO_UNIX_CFLAGS) \ + -I$(srcdir)/cupsfilters/ +cups_browsed_CXXFLAGS = $(cups_browsed_CFLAGS) +cups_browsed_LDADD = \ + $(CUPS_LIBS) \ + $(AVAHI_LIBS) \ + $(AVAHI_GLIB_LIBS) \ + $(GLIB_LIBS) \ + $(GLIB_LIBS) \ + $(GIO_LIBS) \ + $(GIO_UNIX_LIBS) \ + libcupsfilters.la +initrcdir = $(INITDDIR) +initrc_SCRIPTS = utils/cups-browsed +man_MANS = \ + utils/cups-browsed.8 \ + utils/cups-browsed.conf.5 +EXTRA_DIST += utils/cups-browsed.in \ + $(man_MANS) \ + utils/org.cups.cupsd.Notifier.xml +BUILT_SOURCES = $(cups_notifier_sources) +CLEANFILES = $(BUILT_SOURCES) + +# === +# PPD +# === +ppddir = $(datadir)/ppd/cupsfilters +ppd_DATA = \ + ppd/Generic-PDF_Printer-PDF.ppd \ + ppd/HP-Color_LaserJet_CM3530_MFP-PDF.ppd \ + ppd/HP-PhotoSmart_Pro_B8300-hpijs-pdftoijs.ppd \ + ppd/textonly.ppd + +EXTRA_DIST += $(ppd_DATA) + +# ========= +# Scripting +# ========= +if WITH_PHP +phpextensiondir = $(PHPDIR) +phpextension_LTLIBRARIES = libphpcups.la +libphpcups_la_SOURCES = \ + scripting/php/phpcups.c \ + scripting/php/phpcups.h +libphpcups_la_LIBADD = $(CUPS_LIBS) +libphpcups_la_CFLAGS = $(CUPS_CFLAGS) +libphpcups_la_LDFLAGS = -no-undefined +endif # WITH_PHP + +EXTRA_DIST += \ + scripting/perl \ + scripting/php/README \ + scripting/php/phpcups.php + +distclean-local: + rm -rf *.cache *~ + +install-exec-hook: + $(INSTALL) -d -m 755 $(DESTDIR)$(bindir) + $(INSTALL) -d -m 755 $(DESTDIR)$(pkgfilterdir) + $(INSTALL) -d -m 755 $(DESTDIR)$(pkgbackenddir) + +install-data-hook: +if RCLINKS + for level in $(RCLEVELS); do \ + $(INSTALL) -d -m 755 $(DESTDIR)$(INITDIR)/rc$${level}.d; \ + $(LN_S) -f ../init.d/cups-browsed $(DESTDIR)$(INITDIR)/rc$${level}.d/S$(RCSTART)cups-browsed; \ + $(LN_S) -f ../init.d/cups-browsed $(DESTDIR)$(INITDIR)/rc$${level}.d/K$(RCSTOP)cups-browsed; \ + done; \ + $(INSTALL) -d -m 755 $(DESTDIR)$(INITDIR)/rc0.d; \ + $(LN_S) -f ../init.d/cups-browsed $(DESTDIR)$(INITDIR)/rc0.d/K$(RCSTOP)cups-browsed; +endif + $(LN_S) -f pdf.utf-8.simple \ + $(DESTDIR)$(pkgcharsetdir)/pdf.utf-8 + + +uninstall-hook: +if RCLINKS + if test "x$(INITDIR)" != x; then \ + $(RM) $(DESTDIR)$(BUILDROOT)$(INITDIR)/rc?.d/[SK]??cups-browsed || :; \ + rmdir $(DESTDIR)$(BUILDROOT)$(INITDIR)/rc?.d || :;\ + fi +endif + $(RM) $(DESTDIR)$(pkgcharsetdir)/pdf.utf-8 diff --git a/SOURCES/configure.ac b/SOURCES/configure.ac new file mode 100644 index 0000000..036855d --- /dev/null +++ b/SOURCES/configure.ac @@ -0,0 +1,675 @@ +# Process this file with autoconf to create configure. + +AC_PREREQ([2.65]) + +# ==================== +# Version informations +# ==================== +m4_define([cups_filters_version_major],[1]) +m4_define([cups_filters_version_minor],[0]) +m4_define([cups_filters_version_micro],[35]) +m4_define([cups_filters_version],[cups_filters_version_major.cups_filters_version_minor.cups_filters_version_micro]) + +# ============= +# Automake init +# ============= +AC_INIT([cups-filters],[cups_filters_version]) +AC_CONFIG_MACRO_DIR([m4]) +m4_include([m4/ac_define_dir.m4]) +m4_include([m4/ax_compare_version.m4]) +AM_INIT_AUTOMAKE([1.11 gnu dist-xz dist-bzip2]) +AM_SILENT_RULES([yes]) +AC_LANG([C++]) +AC_CONFIG_HEADERS([config.h]) +# Extra defines for the config.h +AH_BOTTOM([ +#ifdef HAVE_LONG_LONG +# define CUPS_LLFMT "%lld" +# define CUPS_LLCAST (long long) +#else +# define CUPS_LLFMT "%ld" +# define CUPS_LLCAST (long) +#endif /* HAVE_LONG_LONG */ + +#ifdef HAVE_ARC4RANDOM +# define CUPS_RAND() arc4random() +# define CUPS_SRAND(v) arc4random_stir() +#elif defined(HAVE_RANDOM) +# define CUPS_RAND() random() +# define CUPS_SRAND(v) srandom(v) +#elif defined(HAVE_LRAND48) +# define CUPS_RAND() lrand48() +# define CUPS_SRAND(v) srand48(v) +#else +# define CUPS_RAND() rand() +# define CUPS_SRAND(v) srand(v) +#endif /* HAVE_ARC4RANDOM */ +]) + +# =========================== +# Find required base packages +# =========================== +AC_PROG_CC +AC_PROG_CXX +AM_PROG_CC_C_O +AC_PROG_CPP +AC_PROG_INSTALL +AC_PROG_LN_S +AC_PROG_MAKE_SET +AC_PROG_LIBTOOL +PKG_PROG_PKG_CONFIG([0.20]) + +# ======================================== +# Specify the fontdir patch if not default +# ======================================== +AC_ARG_WITH([fontdir], + [AS_HELP_STRING([--with-fontdir=path], [Specify path to font config directory (default: fonts/conf.d/).])], + [FONTDIR="$withval"], + [FONTDIR="fonts/conf.d"] +) +AC_SUBST(FONTDIR) + +# ================================ +# Find CUPS internals (no pc file) +# ================================ +AC_ARG_WITH([cups-config], + [AS_HELP_STRING([--with-cups-config=path], [Specify path to cups-config executable.])], + [with_cups_config="$withval"], + [with_cups_config=system] +) + +AS_IF([test "x$with_cups_config" != "xsystem"], [ + CUPSCONFIG=$with_cups_config +], [ + AC_PATH_PROG(CUPSCONFIG, [cups-config]) + AS_IF([test -z "$CUPSCONFIG"], [ + AC_MSG_ERROR([Required cups-config is missing. Please install CUPS developer packages.]) + ]) +]) +CUPS_CFLAGS=`$CUPSCONFIG --cflags` +CUPS_LIBS=`$CUPSCONFIG --image --libs` +CUPS_VERSION=`$CUPSCONFIG --version` +AC_SUBST(CUPS_CFLAGS) +AC_SUBST(CUPS_LIBS) + +CUPS_DATADIR="`$CUPSCONFIG --datadir`" +AC_DEFINE_UNQUOTED(CUPS_DATADIR, "$CUPS_DATADIR", [CUPS datadir]) +AC_SUBST(CUPS_DATADIR) + +CUPS_SERVERROOT="`$CUPSCONFIG --serverroot`" +AC_DEFINE_UNQUOTED(CUPS_SERVERROOT, "$CUPS_SERVERROOT", [CUPS serverroot]) +AC_SUBST(CUPS_SERVERROOT) + +CUPS_FONTPATH="$CUPS_DATADIR/fonts" +AC_DEFINE_UNQUOTED(CUPS_FONTPATH, "$CUPS_FONTPATH", [Path to CUPS fonts dir]) +AC_SUBST(CUPS_FONTPATH) + +CUPS_SERVERBIN="`$CUPSCONFIG --serverbin`" +AC_DEFINE_UNQUOTED(CUPS_SERVERBIN, "$CUPS_SERVERBIN", [Path to CUPS binaries dir]) +AC_SUBST(CUPS_SERVERBIN) + +AX_COMPARE_VERSION([$CUPS_VERSION],[gt],[1.4], [ + AC_DEFINE(CUPS_1_4, 1, [CUPS Version is 1.4 or newer]) +]) +AC_DEFINE(PDFTOPDF, [], [Needed for pdftopdf filter compilation]) +AC_DEFINE_DIR(BANNERTOPDF_DATADIR, "{CUPS_DATADIR}/data", [Directory where bannertopdf finds its data files (PDF templates)]) + +AC_SEARCH_LIBS([dlopen], + [dl], + DLOPEN_LIBS="-ldl", + AC_MSG_ERROR([unable to find the dlopen() function]) +) +AC_SUBST(DLOPEN_LIBS) + +# Transient run-time state dir of CUPS +CUPS_STATEDIR="" +AC_ARG_WITH(cups-rundir, [ --with-cups-rundir set transient run-time state directory of CUPS],CUPS_STATEDIR="$withval",[ + case "$uname" in + Darwin*) + # Darwin (OS X) + CUPS_STATEDIR="$CUPS_SERVERROOT" + ;; + *) + # All others + CUPS_STATEDIR="$localstatedir/run/cups" + ;; + esac]) +AC_DEFINE_UNQUOTED(CUPS_STATEDIR, "$CUPS_STATEDIR", [Transient run-time state dir of CUPS]) +AC_SUBST(CUPS_STATEDIR) + +# Domain socket of CUPS... +CUPS_DEFAULT_DOMAINSOCKET="" +AC_ARG_WITH(cups-domainsocket, [ --with-cups-domainsocket set unix domain socket name used by CUPS +], + default_domainsocket="$withval", + default_domainsocket="") + +if test x$enable_domainsocket != xno -a x$default_domainsocket != xno; then + if test "x$default_domainsocket" = x; then + case "$uname" in + Darwin*) + # Darwin and MaxOS X do their own thing... + CUPS_DEFAULT_DOMAINSOCKET="$localstatedir/run/cupsd" + ;; + *) + # All others use FHS standard... + CUPS_DEFAULT_DOMAINSOCKET="$CUPS_STATEDIR/cups.sock" + ;; + esac + else + CUPS_DEFAULT_DOMAINSOCKET="$default_domainsocket" + fi +fi +AC_DEFINE_UNQUOTED(CUPS_DEFAULT_DOMAINSOCKET, "$CUPS_DEFAULT_DOMAINSOCKET", "Domain socket of CUPS") +AC_SUBST(CUPS_DEFAULT_DOMAINSOCKET) + +# ====================== +# Check system functions +# ====================== +AC_CHECK_FUNCS(strlcat) +AC_CHECK_FUNCS(strlcpy) +AC_CHECK_FUNCS(sigaction) +AC_CHECK_FUNCS(waitpid wait3) +AC_CHECK_FUNCS(strtoll) +AC_CHECK_FUNCS(open_memstream) +AC_CHECK_FUNCS(getline,[],AC_SUBST([GETLINE],['bannertopdf-getline.$(OBJEXT)'])) +AC_CHECK_FUNCS(strcasestr,[],AC_SUBST([STRCASESTR],['pdftops-strcasestr.$(OBJEXT)'])) +AC_SEARCH_LIBS(pow, m) + +# ======================== +# Check for system headers +# ======================== +AC_CHECK_HEADERS([stdlib.h]) +AC_CHECK_HEADERS([sys/stat.h]) +AC_CHECK_HEADERS([sys/types.h]) +AC_CHECK_HEADERS([unistd.h]) +AC_CHECK_HEADERS([zlib.h]) +AC_CHECK_HEADERS([endian.h]) +AC_CHECK_HEADERS([dirent.h]) +AC_CHECK_HEADERS([sys/ioctl.h]) + +# ============= +# Image options +# ============= +AC_ARG_ENABLE([imagefilters], + [AS_HELP_STRING([--disable-imagefilters], [Build the image filters.])], + [enable_imagefilters="$enableval"], + [enable_imagefilters=yes] +) +AM_CONDITIONAL([ENABLE_IMAGEFILTERS], [test "x$enable_imagefilters" != "xno"]) + +# Libraries +AC_ARG_WITH([jpeg], + [AS_HELP_STRING([--without-jpeg], [Disable jpeg support.])], + [with_jpeg="$withval"], + [with_jpeg=yes] +) +AS_IF([test x"$with_jpeg" != "xno"], [ + AC_DEFINE([HAVE_LIBJPEG], [], [Defines if we provide jpeg library.]) + AC_CHECK_HEADERS([jpeglib.h]) + AC_SEARCH_LIBS([jpeg_destroy_decompress], + [jpeg], + LIBJPEG_LIBS="-ljpeg", + AC_MSG_ERROR([jpeg libraries not found.]) + ) + AC_SUBST(LIBJPEG_LIBS) +]) + +AC_ARG_WITH([png], + [AS_HELP_STRING([--without-png], [Disable png support.])], + [with_png="$withval"], + [with_png=yes] +) +AS_IF([test x"$with_png" != "xno"], [ + PKG_CHECK_MODULES([LIBPNG], [libpng]) + AC_DEFINE([HAVE_LIBPNG], [], [Defines if we provide png library.]) +]) + +AC_ARG_WITH([tiff], + [AS_HELP_STRING([--without-tiff], [Disable tiff support.])], + [with_tiff="$withval"], + [with_tiff=yes] +) +AS_IF([test x"$with_tiff" != "xno"], [ + AC_DEFINE([HAVE_LIBTIFF], [], [Defines if we provide tiff library.]) + AC_CHECK_HEADERS([tiff.h]) + AC_SEARCH_LIBS([TIFFReadScanline], + [tiff], + LIBJPEG_LIBS="-ltiff", + AC_MSG_ERROR([tiff libraries not found.]) + ) + AC_SUBST(LIBTIFF_LIBS) +]) + +# ================================== +# Check for modules needed by utils/ +# ================================== + +dnl Avahi for cups-browsed +AVAHI_LIBS="" +AVAHI_CFLAGS="" +AVAHI_GLIB_CFLAGS="" +AVAHI_GLIB_LIBS="" + +AC_ARG_ENABLE([avahi], + [AS_HELP_STRING([--disable-avahi], [Disable DNS Service Discovery support using Avahi.])], + [enable_avahi="$enableval"], + [enable_avahi=yes] +) +AM_CONDITIONAL([ENABLE_AVAHI], [test "x$enable_avahi" != "xno"]) + +AC_ARG_WITH(avahi-libs, + [AS_HELP_STRING([--with-avahi-libs], [Set directory for Avahi library.])], + AVAHI_LIBS="-L$withval $AVAHI_LIBS",) +AC_ARG_WITH(avahi-includes, + [AS_HELP_STRING([--with-avahi-includes], [Set directory for Avahi includes])], + AVAHI_CFLAGS="-I$withval $AVAHI_CFLAGS",) + +if test "x$enable_avahi" != xno; then + PKG_CHECK_MODULES(AVAHI, avahi-client, + [AC_DEFINE(HAVE_AVAHI, [], [Define if you have the avahi library])]) +fi + +AC_SUBST(AVAHI_LIBS) +AC_SUBST(AVAHI_CFLAGS) + +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 "COPYING" +dnl which should have been included with this file. +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 ]) + 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 + +PKG_CHECK_MODULES(GLIB, [glib-2.0 >= 2.30.2]) +AC_SUBST(GLIB_CFLAGS) +AC_SUBST(GLIB_LIBS) + +if test x$enable_avahi != xno; then + PKG_CHECK_MODULES(AVAHI_GLIB, [avahi-glib]) +fi + +AC_SUBST(AVAHI_GLIB_CFLAGS) +AC_SUBST(AVAHI_GLIB_LIBS) + +PKG_CHECK_MODULES(GIO, [gio-2.0]) +AC_SUBST(GIO_CFLAGS) +AC_SUBST(GIO_LIBS) + +PKG_CHECK_MODULES(GIO_UNIX, [gio-unix-2.0]) +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"], + [with_browseremoteprotocols="dnssd cups"] +) +BROWSEREMOTEPROTOCOLS="$with_browseremoteprotocols" +AC_SUBST(BROWSEREMOTEPROTOCOLS) + +dnl Setup init.d locations... +AC_ARG_WITH(rcdir, [AS_HELP_STRING([--with-rcdir], [Set path for rc scripts])],rcdir="$withval",rcdir="") +AC_ARG_WITH(rclevels, [AS_HELP_STRING([--with-rclevels], [Set run levels for rc scripts])],rclevels="$withval",rclevels="2 3 5") +AC_ARG_WITH(rcstart, [AS_HELP_STRING([--with-rcstart], [Set start number for rc scripts])],rcstart="$withval",rcstart="99") +AC_ARG_WITH(rcstop, [AS_HELP_STRING([--with-rcstop], [Set stop number for rc scripts])],rcstop="$withval",rcstop="00") + +INITDIR="" +INITDDIR="" +RCLEVELS="$rclevels" +RCSTART="$rcstart" +RCSTOP="$rcstop" + +if test x$rcdir = x; then + case "`uname`" in + FreeBSD* | OpenBSD* | MirBSD* | ekkoBSD*) + # FreeBSD and OpenBSD + ;; + + Linux | GNU | GNU/k*BSD*) + # Linux/HURD seems to choose an init.d directory at random... + if test -d /sbin/init.d; then + # SuSE + INITDIR="/sbin/init.d" + else + if test -d /etc/init.d; then + # Others + INITDIR="/etc" + else + # RedHat + INITDIR="/etc/rc.d" + fi + fi + RCSTART="82" + RCSTOP="35" + ;; + + NetBSD*) + # NetBSD + INITDDIR="/etc/rc.d" + ;; + + *) + INITDIR="/etc" + ;; + + esac +elif test "x$rcdir" != xno; then + if test "x$rclevels" = x; then + INITDDIR="$rcdir" + else + INITDIR="$rcdir" + fi +fi + +AM_CONDITIONAL([RCLINKS], [test "x$INITDIR" != "x"]) + +if test "x${INITDIR}" != "x" -a "x${INITDDIR}" = "x"; then + INITDDIR="${INITDIR}/init.d" +fi + +AC_SUBST(INITDIR) +AC_SUBST(INITDDIR) +AC_SUBST(RCLEVELS) +AC_SUBST(RCSTART) +AC_SUBST(RCSTOP) + +# ====================================== +# Check for various pdf required modules +# ====================================== +PKG_CHECK_MODULES([LCMS], [lcms2], [lcms2=yes], [lcms2=no]) +AS_IF([test x"$lcms2" = "xno"], [ + PKG_CHECK_MODULES([LCMS], [lcms]) + AC_DEFINE([USE_LCMS1], [1], [Defines if use lcms1]) +]) +PKG_CHECK_MODULES([FREETYPE], [freetype2], [AC_DEFINE([HAVE_FREETYPE_H], [1], [Have FreeType2 include files])]) +PKG_CHECK_MODULES([FONTCONFIG], [fontconfig >= 2.0.0]) +PKG_CHECK_MODULES([IJS], [ijs], [have_ijs=yes], [have_ijs=no]) +PKG_CHECK_MODULES([ZLIB], [zlib]) +AC_DEFINE([HAVE_LIBZ], [], [Define that we use zlib]) +PKG_CHECK_MODULES([LIBQPDF], [libqpdf >= 3.0.2]) + +# ================= +# Check for Poppler +# ================= +AC_ARG_ENABLE(poppler, AS_HELP_STRING([--enable-poppler],[enable Poppler-based filters]), + enable_poppler=$enableval,enable_poppler=yes) +AM_CONDITIONAL(ENABLE_POPPLER, test x$enable_poppler = xyes) +if test x$enable_poppler = xyes; then + PKG_CHECK_MODULES([POPPLER], [poppler >= 0.18]) + AC_CHECK_HEADER([poppler/cpp/poppler-version.h], [AC_DEFINE([HAVE_CPP_POPPLER_VERSION_H],,[Define if you have Poppler's "cpp/poppler-version.h" header file.])], []) +fi + +# =============== +# Check for D-Bus +# =============== +AC_ARG_ENABLE(dbus, AS_HELP_STRING([--enable-dbus],[enable DBus CMS code]), + enable_dbus=$enableval,enable_dbus=yes) +AM_CONDITIONAL(BUILD_DBUS, test x$enable_dbus = xyes) +if test x$enable_dbus = xyes; then + PKG_CHECK_MODULES(DBUS, dbus-1) +fi + +# =================================== +# Check for large files and long long +# =================================== +AC_SYS_LARGEFILE +LARGEFILE="" +AS_IF([test x"$enable_largefile" != "xno"], [ + LARGEFILE="-D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE" + AS_IF([test x"$ac_cv_sys_large_files" = "x1"], [LARGEFILE="$LARGEFILE -D_LARGE_FILES"]) + AS_IF([test x"$ac_cv_sys_file_offset_bits" = "x64"], [LARGEFILE="$LARGEFILE -D_FILE_OFFSET_BITS=64"]) +]) +AC_SUBST(LARGEFILE) + +AC_CHECK_TYPE(long long, [long_long_found=yes], [long_long_found=no]) +AS_IF([test x"$long_long_found" = "xyes"], [ + AC_DEFINE([HAVE_LONG_LONG], [], [Platform supports long long type]) +]) + +# ================ +# Check for pdf2ps +# ================ +AC_ARG_WITH([pdftops], + [AS_HELP_STRING([--with-pdftops=value], [Set which pdftops to use (gs,pdftops,pdftocairo,acroread).])], + [with_pdftops="$withval"], + [with_pdftops=gs] +) +AS_CASE([x$with_pdftops], + [xgs|xpdftops|xpdftocairo|xacroread], [], + [AC_MSG_ERROR([Unknown value of with-pdftops provided: $with_pdftops])] +) +AC_ARG_WITH([gs-path], + [AS_HELP_STRING([--with-gs-path=value], [Set path to ghostcript binary (default: system).])], + [with_gs_path="$withval"], + [with_gs_path=system] +) +AC_ARG_WITH([pdftops-path], + [AS_HELP_STRING([--with-pdftops-path=value], [Set path to pdftops/ghostscript binary (default: system).])], + [with_pdftops_path="$withval"], + [with_pdftops_path=system] +) +AC_ARG_WITH([pdftocairo-path], + [AS_HELP_STRING([--with-pdftocairo-path=value], [Set path to pdftocairo binary (default: system).])], + [with_pdftocairo_path="$withval"], + [with_pdftocairo_path=system] +) +AC_ARG_WITH([acroread-path], + [AS_HELP_STRING([--with-acroread-path=value], [Set path to acroread binary (default: system).])], + [with_acroread_path="$withval"], + [with_acroread_path=system] +) +AC_ARG_WITH([pdftops-maxres], + [AS_HELP_STRING([--with-pdftops-maxres=value], [Set maximum image rendering resolution for pdftops filter (0, 75, 150, 300, 600, 1200, 2400, 4800, 90, 180, 360, 720, 1440, 2880, 5760, unlimited). Default: 1440])], + [with_pdftops_maxres="$withval"], + [with_pdftops_maxres=1440] +) +AS_CASE([x$with_pdftops_maxres], + [x0|x75|x150|x300|x600|x1200|x2400|x4800|x90|x180|x360|x720|x1440|x2880|x5760], [CUPS_PDFTOPS_MAXRES=$with_pdftops_maxres], + [xunlimited], [CUPS_PDFTOPS_MAXRES=0], + [AC_MSG_ERROR([Unknown value of with-pdftops-maxres provided: $with_pdftops])] +) + +AS_IF([test "x$with_gs_path" != "xsystem"], [ + CUPS_GHOSTSCRIPT="$with_gs_path" +], [ + AC_PATH_PROG(CUPS_GHOSTSCRIPT, [gs], [AC_MSG_ERROR([Required gs binary is missing. Please install ghostscript-gpl package.])]) +]) +AS_IF([test "x$CUPS_GHOSTSCRIPT" != "x"], [ + AC_DEFINE([HAVE_GHOSTSCRIPT], [], [Define that we provide ghostscript binary]) + AS_IF([test x"$with_pdftops" = xgs], [AC_DEFINE_UNQUOTED([CUPS_PDFTOPS_RENDERER], [GS], [Define default renderer])]) + + AC_MSG_CHECKING(whether gs supports the ps2write device) + AS_IF([`$CUPS_GHOSTSCRIPT -h 2>&1 | grep -q ps2write`], [ + AC_MSG_RESULT([yes]) + AC_DEFINE([HAVE_GHOSTSCRIPT_PS2WRITE], [], [gs supports ps2write]) + ], [ + AC_MSG_RESULT([no]) + ]) +]) + +AS_IF([test "x$with_pdftops_path" != "xsystem"], [ + CUPS_PDFTOPS="$with_pdftops" +], [ + AC_PATH_PROG(CUPS_PDFTOPS, [pdftops], [AC_MSG_ERROR([Required pdftops is missing. Please install CUPS developer packages.])]) +]) +AS_IF([test "x$CUPS_PDFTOPS" != "x"], [ + AC_DEFINE([HAVE_POPPLER_PDFTOPS], [], [Define that we provide poppler pdftops.]) + AS_IF([test x"$with_pdftops" = xpdftops], [AC_DEFINE_UNQUOTED([CUPS_PDFTOPS_RENDERER], [PDFTOPS], [Define default renderer])]) + + AC_MSG_CHECKING([whether pdftops supports -origpagesizes]) + AS_IF([`$CUPS_PDFTOPS -h 2>&1 | grep -q -- -origpagesizes`], [ + AC_MSG_RESULT([yes]) + AC_DEFINE([HAVE_POPPLER_PDFTOPS_WITH_ORIGPAGESIZES], [] , [pdftops supports -origpagesizes.]) + ], [ + AC_MSG_RESULT([no]) + ]) + AC_MSG_CHECKING([whether pdftops supports -r]) + AS_IF([`$CUPS_PDFTOPS -h 2>&1 | grep -q -- '-r '`], [ + AC_MSG_RESULT([yes]) + AC_DEFINE([HAVE_POPPLER_PDFTOPS_WITH_RESOLUTION], [] , [pdftops supports -r argument.]) + ], [ + AC_MSG_RESULT([no]) + ]) +]) +AS_IF([test "x$with_pdftocairo_path" != "xsystem"], [ + CUPS_PDFTOPS="$with_pdftocairo_path" +], [ + AC_PATH_PROG(CUPS_PDFTOCAIRO, [pdftocairo], [AC_MSG_ERROR([Required pdftocairo is missing. Please install Poppler developer packages.])]) +]) +AS_IF([test "x$CUPS_PDFTOCAIRO" != "x"], [ + AC_DEFINE([HAVE_POPPLER_PDFTOCAIRO], [], [Define that we provide poppler pdftocairo.]) + AS_IF([test x"$with_pdftops" = xpdftocairo], [AC_DEFINE_UNQUOTED([CUPS_PDFTOPS_RENDERER], [PDFTOCAIRO], [Define default renderer])]) +]) +AS_IF([test "x$with_acroread_path" != "xsystem"], [ + CUPS_ACROREAD="$with_acroread_path" +], [ + AC_PATH_PROG(CUPS_ACROREAD, [acroread], [AC_MSG_ERROR([Required acroread binary is missing. Please install acroread package.])]) +]) +AS_IF([test "x$CUPS_ACROREAD" != "x"], [ + AC_DEFINE([HAVE_ACROREAD], [], [Define that we provide acroread.]) + AS_IF([test x"$with_pdftops" = xacroread], [AC_DEFINE_UNQUOTED([CUPS_PDFTOPS_RENDERER], [ACROREAD], [Define default renderer])]) +]) + +AC_DEFINE_UNQUOTED([CUPS_GHOSTSCRIPT], "$CUPS_GHOSTSCRIPT", [gs binary to use]) +AC_DEFINE_UNQUOTED([CUPS_POPPLER_PDFTOPS], "$CUPS_PDFTOPS", [pdftops binary to use.]) +AC_DEFINE_UNQUOTED([CUPS_POPPLER_PDFTOCAIRO], "$CUPS_PDFTOCAIRO", [pdftocairo binary to use.]) +AC_DEFINE_UNQUOTED([CUPS_ACROREAD], "$CUPS_ACROREAD", [acroread binary to use.]) +AC_DEFINE_UNQUOTED([CUPS_PDFTOPS_MAX_RESOLUTION], [$CUPS_PDFTOPS_MAXRES], [max resolution used for pdftops when converting images]) + +# ============= +# Check for php +# ============= +# NOTE: This stuff is broken, requires internal cups headers. +AC_ARG_WITH([php], + [AS_HELP_STRING([--with-php], [Determine whether to build php cups extension.])], + [with_php="$withval"], + [with_php=no] +) +AC_ARG_WITH([php-config], + [AS_HELP_STRING([--with-php-config=path], [Specify path to php-config executable.])], + [with_php_config="$withval"], + [with_php_config=system] +) +AM_CONDITIONAL([WITH_PHP], [test "x$with_php" = "xyes"]) +AS_IF([test x"$with_php" = "xyes"], [ + AS_IF([test "x$with_php_config" != "xsystem"], [ + PHPCONFIG=$with_php_config + ], [ + AC_PATH_PROG(PHPCONFIG, [php-config]) + AS_IF([test -z "$PHPCONFIG"], [ + AC_MSG_ERROR([Required php-config is missing. Please install PHP developer packages.]) + ]) + ]) + PHPDIR="`$PHPCONFIG --extension-dir`" + AC_SUBST(PHPDIR) +]) + +# ========= +# Test ARGS +# ========= +AC_ARG_WITH([test-font-path], + [AS_HELP_STRING([--with-test-font-path=value], [Set path to pdftops/ghostscript binary (default: /usr/share/fonts/dejavu/DejaVuSans.ttf).])], + [with_test_font_path="$withval"], + [with_test_font_path="/usr/share/fonts/dejavu/DejaVuSans.ttf"] +) +AC_DEFINE_UNQUOTED([TESTFONT], ["$with_test_font_path"], [Path to font used in tests]) + +# ================ +# Check for cflags +# ================ +AC_ARG_ENABLE([werror], + [AS_HELP_STRING([--enable-werror], [Treat all warnings as errors, useful for development.])], + [enable_werror="$enableval"], + [enable_werror=no] +) +AS_IF([test x"$enable_werror" = "xyes"], [ + CFLAGS="$CFLAGS -Werror" +]) +AS_IF([test x"$GCC" = "xyes"], [ + # Be tough with warnings and produce less careless code + CFLAGS="$CFLAGS -Wall -pedantic -std=gnu99" + CXXFLAGS="$CXXFLAGS -Wall -pedantic" # -Weffc++" # TODO: enable when it does not print 1MB of warnings +]) +CFLAGS="$CFLAGS -D_GNU_SOURCE" +CXXFLAGS="$CXXFLAGS -D_GNU_SOURCE" + +# ===================== +# Prepare all .in files +# ===================== +AC_CONFIG_FILES([ + libcupsfilters.pc + libfontembed.pc + Makefile + utils/cups-browsed + utils/cups-browsed.conf +]) +AC_OUTPUT + +# ============================================== +# Display final informations about configuration +# ============================================== +AC_MSG_NOTICE([ +============================================================================== +Environment settings: + CFLAGS: ${CFLAGS} + CXXFLAGS: ${CXXFLAGS} + LDFLAGS: ${LDFLAGS} +Build configuration: + cups-config: ${with_cups_config} + font directory: ${sysconfdir}/${FONTDIR} + init directory: ${INITDDIR} + cups dom socket: ${CUPS_DEFAULT_DOMAINSOCKET} + gs-path: ${with_gs_path} + imagefilters: ${enable_imagefilters} + jpeg: ${with_jpeg} + pdftocairo-path: ${with_pdftocairo_path} + pdftops: ${with_pdftops} + pdftops-path: ${with_pdftops_path} + png: ${with_png} + php: ${with_php} + php-config: ${with_php_config} + test-font: ${with_test_font_path} + tiff: ${with_tiff} + avahi: ${enable_avahi} + dbus: ${enable_dbus} + browsing: ${with_browseremoteprotocols} + werror: ${enable_werror} +============================================================================== +]) diff --git a/SOURCES/cups-browsed.service b/SOURCES/cups-browsed.service deleted file mode 100644 index 144956c..0000000 --- a/SOURCES/cups-browsed.service +++ /dev/null @@ -1,10 +0,0 @@ -[Unit] -Description=Make remote CUPS printers available locally -After=cups.service avahi-daemon.service -Wants=cups.service avahi-daemon.service - -[Service] -ExecStart=/usr/sbin/cups-browsed - -[Install] -WantedBy=multi-user.target diff --git a/SOURCES/cups-filters-CVE-2014-4337.patch b/SOURCES/cups-filters-CVE-2014-4337.patch deleted file mode 100644 index b3b5d43..0000000 --- a/SOURCES/cups-filters-CVE-2014-4337.patch +++ /dev/null @@ -1,254 +0,0 @@ -diff -up cups-filters-1.0.35/NEWS.CVE-2014-4337 cups-filters-1.0.35/NEWS -diff -up cups-filters-1.0.35/utils/cups-browsed.c.CVE-2014-4337 cups-filters-1.0.35/utils/cups-browsed.c ---- cups-filters-1.0.35/utils/cups-browsed.c.CVE-2014-4337 2014-10-08 13:33:12.192067445 +0100 -+++ cups-filters-1.0.35/utils/cups-browsed.c 2014-10-08 13:54:45.742569979 +0100 -@@ -298,6 +298,75 @@ create_local_queue (const char *name, - return p; - } - -+/* -+ * Remove all illegal characters and replace each group of such characters -+ * by a single dash, return a free()-able string. -+ * -+ * mode = 0: Only allow letters, numbers, and dashes, for turning make/model -+ * info into a valid print queue name or into a string which can -+ * be supplied as option value in a filter command line without -+ * need of quoting -+ * mode = 1: Allow also '/', '.', ',', '_', for cleaning up MIME type -+ * strings (here available Page Description Languages, PDLs) to -+ * supply them on a filter command line without quoting -+ * -+ * Especially this prevents from arbitrary code execution by interface scripts -+ * generated for print queues to native IPP printers when a malicious IPP -+ * print service with forged PDL and/or make/model info gets broadcasted into -+ * the local network. -+ */ -+ -+char * /* O - Cleaned string */ -+remove_bad_chars(const char *str_orig, /* I - Original string */ -+ int mode) /* I - 0: Make/Model, queue name */ -+ /* 1: MIME types/PDLs */ -+{ -+ int i, j; -+ int havedash = 0; -+ char *str; -+ -+ if (str_orig == NULL) -+ return NULL; -+ -+ str = strdup(str_orig); -+ -+ /* for later str[strlen(str)-1] access */ -+ if (strlen(str) < 1) -+ return str; -+ -+ for (i = 0, j = 0; i < strlen(str); i++, j++) { -+ if (((str[i] >= 'A') && (str[i] <= 'Z')) || -+ ((str[i] >= 'a') && (str[i] <= 'z')) || -+ ((str[i] >= '0') && (str[i] <= '9')) || -+ (mode == 1 && (str[i] == '/' || str[i] == '_' || -+ str[i] == '.' || str[i] == ','))) { -+ /* Letter or number, keep it */ -+ havedash = 0; -+ } else { -+ /* Replace all other characters by a single '-' */ -+ if (havedash == 1) -+ j --; -+ else { -+ havedash = 1; -+ str[j] = '-'; -+ } -+ } -+ } -+ /* Add terminating zero */ -+ str[j] = '\0'; -+ /* Cut off trailing dashes */ -+ while (str[strlen(str)-1] == '-') -+ str[strlen(str)-1] = '\0'; -+ -+ /* Cut off leading dashes */ -+ i = 0; -+ while (str[i] == '-') -+ ++i; -+ -+ /* keep a free()-able string. +1 for trailing \0 */ -+ return memmove(str, str + i, strlen(str) - i + 1); -+} -+ - gboolean handle_cups_queues(gpointer unused) { - remote_printer_t *p; - http_t *http; -@@ -392,7 +461,7 @@ gboolean handle_cups_queues(gpointer unu - } - if (default_printer_name) - break; -- } -+ } - } - if (default_printer_name && - !strcasecmp(default_printer_name, p->name)) { -@@ -572,19 +641,30 @@ void generate_local_queue(const char *ho - const char *name, - const char *type, - const char *domain) { -- char *remote_queue, *remote_host; -+ char *remote_queue = NULL, *remote_host = NULL; - remote_printer_t *p; -- char *backup_queue_name, *local_queue_name = NULL; -- cups_dest_t *dests, *dest; -+ char *backup_queue_name = NULL, *local_queue_name = NULL; -+ cups_dest_t *dests = NULL, *dest = NULL; - int i, num_dests; -- const char *val; -+ size_t hl = 0; -+ const char *val = NULL; - - /* This is a remote CUPS queue, find queue name and host name */ -- remote_queue = resource + 9; -- remote_host = strdup(host); -- if (!strcmp(remote_host + strlen(remote_host) - 6, ".local")) -+ if (strncasecmp(resource, "printers/", 9)) { -+ debug_printf("cups-browsed: resource does not begin 'printers/'\n"); -+ return; -+ } -+ -+ remote_queue = remove_bad_chars(resource + 9, 0); -+ /* Find the remote host name. -+ * Used in constructing backup_queue_name, so need to sanitize. -+ * strdup() is called inside remove_bad_chars() and result is free()-able. -+ */ -+ remote_host = remove_bad_chars(host, 1); -+ hl = strlen(remote_host); -+ if (hl > 6 && !strcmp(remote_host + strlen(remote_host) - 6, ".local")) - remote_host[strlen(remote_host) - 6] = '\0'; -- if (!strcmp(remote_host + strlen(remote_host) - 7, ".local.")) -+ if (hl > 7 && !strcmp(remote_host + strlen(remote_host) - 7, ".local.")) - remote_host[strlen(remote_host) - 7] = '\0'; - debug_printf("cups-browsed: Found CUPS queue: %s on host %s.\n", - remote_queue, remote_host); -@@ -592,7 +672,7 @@ void generate_local_queue(const char *ho - /* Check if there exists already a CUPS queue with the - requested name Try name@host in such a case and if - this is also taken, ignore the printer */ -- if ((backup_queue_name = malloc((strlen(remote_queue) + -+ if ((backup_queue_name = malloc((strlen(remote_queue) + - strlen(remote_host) + 2) * - sizeof(char))) == NULL) { - debug_printf("cups-browsed: ERROR: Unable to allocate memory.\n"); -@@ -639,6 +719,7 @@ void generate_local_queue(const char *ho - local_queue_name); - free (backup_queue_name); - free (remote_host); -+ free (remote_queue); - cupsFreeDests(num_dests, dests); - return; - } -@@ -724,6 +805,7 @@ void generate_local_queue(const char *ho - - free (backup_queue_name); - free (remote_host); -+ free (remote_queue); - - if (p) - debug_printf("cups-browsed: Bonjour IDs: Service name: \"%s\", " -@@ -958,12 +1040,18 @@ found_cups_printer (const char *remote_h - char local_resource[HTTP_MAX_URI]; - char *c; - -+ 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), -- username, sizeof(username), -- host, sizeof(host), -+ scheme, sizeof(scheme) - 1, -+ username, sizeof(username) - 1, -+ host, sizeof(host) - 1, - &port, -- resource, sizeof(resource)); -+ resource, sizeof(resource)- 1); - - /* Check this isn't one of our own broadcasts */ - for (iface = cupsArrayFirst (netifs); -@@ -1071,7 +1159,12 @@ process_browse_data (GIOChannel *source, - char remote_host[256]; - char uri[1024]; - char info[1024]; -- char *c; -+ char *c = NULL, *end = NULL; -+ -+ memset(packet, 0, sizeof(packet)); -+ memset(remote_host, 0, sizeof(remote_host)); -+ memset(uri, 0, sizeof(uri)); -+ memset(info, 0, sizeof(info)); - - srclen = sizeof (srcaddr); - got = recvfrom (browsesocket, packet, sizeof (packet) - 1, 0, -@@ -1084,7 +1177,7 @@ process_browse_data (GIOChannel *source, - } - - packet[got] = '\0'; -- httpAddrString (&srcaddr, remote_host, sizeof (remote_host)); -+ httpAddrString (&srcaddr, remote_host, sizeof (remote_host) - 1); - - /* Check this packet is allowed */ - if (!allowed ((struct sockaddr *) &srcaddr)) { -@@ -1102,28 +1195,42 @@ process_browse_data (GIOChannel *source, - } - - info[0] = '\0'; -+ -+ /* do not read OOB */ -+ end = packet + sizeof(packet); - c = strchr (packet, '\"'); -+ if (c >= end) -+ return TRUE; -+ - if (c) { - /* Skip location field */ -- for (c++; *c != '\"'; c++) -+ for (c++; c < end && *c != '\"'; c++) - ; - -+ if (c >= end) -+ return TRUE; -+ - if (*c == '\"') { -- for (c++; isspace(*c); c++) -+ for (c++; c < end && isspace(*c); c++) - ; - } - -+ if (c >= end) -+ return TRUE; -+ - /* Is there an info field? */ - if (*c == '\"') { - int i; - c++; - for (i = 0; -- i < sizeof (info) - 1 && *c != '\"'; -+ i < sizeof (info) - 1 && *c != '\"' && c < end; - i++, c++) - info[i] = *c; - info[i] = '\0'; - } - } -+ if (c >= end) -+ return TRUE; - - found_cups_printer (remote_host, uri, info); - recheck_timer (); -@@ -1332,7 +1439,7 @@ send_browse_data (gpointer data) - while (attr && ippGetGroupTag(attr) == IPP_TAG_PRINTER) { - const char *attrname = ippGetName(attr); - int value_tag = ippGetValueTag(attr); -- -+ - if (!strcmp(attrname, "printer-type") && - value_tag == IPP_TAG_ENUM) { - type = ippGetInteger(attr, 0); diff --git a/SOURCES/cups-filters-CVE-2014-4338.patch b/SOURCES/cups-filters-CVE-2014-4338.patch deleted file mode 100644 index 108427e..0000000 --- a/SOURCES/cups-filters-CVE-2014-4338.patch +++ /dev/null @@ -1,51 +0,0 @@ -diff -up cups-filters-1.0.35/utils/cups-browsed.c.CVE-2014-4338 cups-filters-1.0.35/utils/cups-browsed.c ---- cups-filters-1.0.35/utils/cups-browsed.c.CVE-2014-4338 2014-10-08 14:10:19.389201254 +0100 -+++ cups-filters-1.0.35/utils/cups-browsed.c 2014-10-08 16:24:09.648892671 +0100 -@@ -91,7 +91,8 @@ typedef struct netif_s { - /* Data structure for browse allow/deny rules */ - typedef enum allow_type_e { - ALLOW_IP, -- ALLOW_NET -+ ALLOW_NET, -+ ALLOW_INVALID - } allow_type_t; - typedef struct allow_s { - allow_type_t type; -@@ -1094,6 +1095,9 @@ allowed (struct sockaddr *srcaddr) - allow; - allow = cupsArrayNext (browseallow)) { - switch (allow->type) { -+ case ALLOW_INVALID: -+ break; -+ - case ALLOW_IP: - switch (srcaddr->sa_family) { - case AF_INET: -@@ -1699,6 +1703,8 @@ read_browseallow_value (const char *valu - char *p; - struct in_addr addr; - allow_t *allow = calloc (1, sizeof (allow_t)); -+ if (value == NULL) -+ goto fail; - p = strchr (value, '/'); - if (p) { - char *s = strdup (value); -@@ -1741,7 +1747,8 @@ read_browseallow_value (const char *valu - return 0; - - fail: -- free (allow); -+ allow->type = ALLOW_INVALID; -+ cupsArrayAdd (browseallow, allow); - return 1; - } - -@@ -1798,7 +1805,7 @@ read_configuration (const char *filename - debug_printf("cups-browsed: Adding BrowsePoll server: %s\n", value); - BrowsePoll[NumBrowsePoll++] = strdup (value); - } -- } else if (!strcasecmp(line, "BrowseAllow") && value) -+ } else if (!strcasecmp(line, "BrowseAllow")) - if (read_browseallow_value (value)) - debug_printf ("cups-browsed: BrowseAllow value \"%s\" not understood\n", - value); diff --git a/SOURCES/cups-filters-browsed-efficiency.patch b/SOURCES/cups-filters-browsed-efficiency.patch deleted file mode 100644 index 9b532c8..0000000 --- a/SOURCES/cups-filters-browsed-efficiency.patch +++ /dev/null @@ -1,2906 +0,0 @@ -diff -up cups-filters-1.0.35/utils/cups-browsed.c.browsed-efficiency cups-filters-1.0.35/utils/cups-browsed.c ---- cups-filters-1.0.35/utils/cups-browsed.c.browsed-efficiency 2015-06-25 16:48:33.667228224 +0100 -+++ cups-filters-1.0.35/utils/cups-browsed.c 2015-06-25 16:48:48.215194502 +0100 -@@ -23,15 +23,16 @@ - - #include - #include --#include - #if defined(__OpenBSD__) - #include - #endif /* __OpenBSD__ */ -+#include - #include - #include -+#include - #include - #include --#include -+#include - #include - #include - #include -@@ -62,17 +63,20 @@ - - /* Status of remote printer */ - typedef enum printer_status_e { -- STATUS_UNCONFIRMED = 0, -- STATUS_CONFIRMED, -- STATUS_TO_BE_CREATED, -- STATUS_BROWSE_PACKET_RECEIVED, -- STATUS_DISAPPEARED -+ STATUS_UNCONFIRMED = 0, /* Generated in a previous session */ -+ STATUS_CONFIRMED, /* Avahi confirms UNCONFIRMED printer */ -+ STATUS_TO_BE_CREATED, /* Scheduled for creation */ -+ STATUS_BROWSE_PACKET_RECEIVED,/* Scheduled for creation with timeout */ -+ STATUS_DISAPPEARED /* Scheduled for removal */ - } printer_status_t; - - /* Data structure for remote printers */ - typedef struct remote_printer_s { - char *name; - char *uri; -+ char *ppd; -+ char *model; -+ char *ifscript; - printer_status_t status; - time_t timeout; - int duplicate; -@@ -100,13 +104,62 @@ typedef struct allow_s { - http_addr_t mask; - } allow_t; - -+/* Data struct for a printer discovered using BrowsePoll */ -+typedef struct browsepoll_printer_s { -+ char *uri_supported; -+ char *info; -+} browsepoll_printer_t; -+ -+/* Data structure for a BrowsePoll server */ -+typedef struct browsepoll_s { -+ char *server; -+ int port; -+ int major; -+ int minor; -+ gboolean can_subscribe; -+ int subscription_id; -+ int sequence_number; -+ -+ /* Remember which printers we discovered. This way we can just ask -+ * if anything has changed, and if not we know these printers are -+ * still there. */ -+ GList *printers; /* of browsepoll_printer_t */ -+} browsepoll_t; -+ -+/* Local printer (key is name) */ -+typedef struct local_printer_s { -+ char *device_uri; -+ gboolean cups_browsed_controlled; -+} local_printer_t; -+ -+/* Browse data to send for local printer */ -+typedef struct browse_data_s { -+ int type; -+ int state; -+ char *uri; -+ char *location; -+ char *info; -+ char *make_model; -+ char *browse_options; -+} browse_data_t; -+ - cups_array_t *remote_printers; - static cups_array_t *netifs; - static cups_array_t *browseallow; -+static gboolean browseallow_all = FALSE; -+ -+static GHashTable *local_printers; -+static browsepoll_t *local_printers_context = NULL; -+static http_t *local_conn = NULL; -+static gboolean inhibit_local_printers_update = FALSE; -+ -+static GList *browse_data = NULL; - - static GMainLoop *gmainloop = NULL; - #ifdef HAVE_AVAHI - static AvahiGLibPoll *glib_poll = NULL; -+static AvahiClient *client = NULL; -+static AvahiServiceBrowser *sb1 = NULL, *sb2 = NULL; - #endif /* HAVE_AVAHI */ - static guint queues_timer_id = (guint) -1; - static int browsesocket = -1; -@@ -118,12 +171,22 @@ static unsigned int BrowseRemoteProtocol - static unsigned int BrowseInterval = 60; - static unsigned int BrowseTimeout = 300; - static uint16_t BrowsePort = 631; --static char **BrowsePoll = NULL; -+static browsepoll_t **BrowsePoll = NULL; - static size_t NumBrowsePoll = 0; -+static char *DomainSocket = NULL; -+static unsigned int CreateIPPPrinterQueues = 0; -+static int autoshutdown = 0; -+static int autoshutdown_avahi = 0; -+static int autoshutdown_timeout = 30; -+static guint autoshutdown_exec_id = 0; - - static int debug = 0; - - static void recheck_timer (void); -+static void browse_poll_create_subscription (browsepoll_t *context, -+ http_t *conn); -+static gboolean browse_poll_get_notifications (browsepoll_t *context, -+ http_t *conn); - - #if (CUPS_VERSION_MAJOR > 1) || (CUPS_VERSION_MINOR > 5) - #define HAVE_CUPS_1_6 1 -@@ -211,6 +274,15 @@ ippNextAttribute(ipp_t *ipp) - return (ipp->current = ipp->current->next); - } - -+int -+ippSetVersion(ipp_t *ipp, int major, int minor) -+{ -+ if (!ipp || major < 0 || minor < 0) -+ return (0); -+ ipp->request.any.version[0] = major; -+ ipp->request.any.version[1] = minor; -+ return (1); -+} - #endif - - void debug_printf(const char *format, ...) { -@@ -223,16 +295,425 @@ void debug_printf(const char *format, .. - } - } - -+static const char * -+password_callback (const char *prompt, -+ http_t *http, -+ const char *method, -+ const char *resource, -+ void *user_data) -+{ -+ return NULL; -+} -+ -+static http_t * -+http_connect_local (void) -+{ -+ if (!local_conn) -+ local_conn = httpConnectEncrypt(cupsServer(), ippPort(), -+ cupsEncryption()); -+ -+ return local_conn; -+} -+ -+static void -+http_close_local (void) -+{ -+ if (local_conn) { -+ httpClose (local_conn); -+ local_conn = NULL; -+ } -+} -+ -+static local_printer_t * -+new_local_printer (const char *device_uri, -+ gboolean cups_browsed_controlled) -+{ -+ local_printer_t *printer = g_malloc (sizeof (local_printer_t)); -+ printer->device_uri = strdup (device_uri); -+ printer->cups_browsed_controlled = cups_browsed_controlled; -+ return printer; -+} -+ -+static void -+free_local_printer (gpointer data) -+{ -+ local_printer_t *printer = data; -+ free (printer->device_uri); -+ free (printer); -+} -+ -+static gboolean -+local_printer_has_uri (gpointer key, -+ gpointer value, -+ gpointer user_data) -+{ -+ local_printer_t *printer = value; -+ char *device_uri = user_data; -+ return g_str_equal (printer->device_uri, device_uri); -+} -+ -+static void -+local_printers_create_subscription (http_t *conn) -+{ -+ if (!local_printers_context) { -+ local_printers_context = g_malloc0 (sizeof (browsepoll_t)); -+ local_printers_context->server = "localhost"; -+ local_printers_context->port = BrowsePort; -+ local_printers_context->can_subscribe = TRUE; -+ } -+ -+ browse_poll_create_subscription (local_printers_context, conn); -+} -+ -+static void -+get_local_printers (void) -+{ -+ cups_dest_t *dests = NULL; -+ int num_dests = cupsGetDests (&dests); -+ debug_printf ("cups-browsed [BrowsePoll localhost:631]: cupsGetDests\n"); -+ g_hash_table_remove_all (local_printers); -+ for (int i = 0; i < num_dests; i++) { -+ const char *val; -+ cups_dest_t *dest = &dests[i]; -+ local_printer_t *printer; -+ gboolean cups_browsed_controlled; -+ const char *device_uri = cupsGetOption ("device-uri", -+ dest->num_options, -+ dest->options); -+ val = cupsGetOption (CUPS_BROWSED_MARK, -+ dest->num_options, -+ dest->options); -+ cups_browsed_controlled = val && (!strcasecmp (val, "yes") || -+ !strcasecmp (val, "on") || -+ !strcasecmp (val, "true")); -+ printer = new_local_printer (device_uri, -+ cups_browsed_controlled); -+ g_hash_table_insert (local_printers, -+ g_strdup (dest->name), -+ printer); -+ } -+ -+ cupsFreeDests (num_dests, dests); -+} -+ -+static browse_data_t * -+new_browse_data (int type, int state, const gchar *uri, -+ const gchar *location, const gchar *info, -+ const gchar *make_model, const gchar *browse_options) -+{ -+ browse_data_t *data = g_malloc (sizeof (browse_data_t)); -+ data->type = type; -+ data->state = state; -+ data->uri = g_strdup (uri); -+ data->location = g_strdup (location); -+ data->info = g_strdup (info); -+ data->make_model = g_strdup (make_model); -+ data->browse_options = g_strdup (browse_options); -+ return data; -+} -+ -+static void -+browse_data_free (gpointer data) -+{ -+ browse_data_t *bdata = data; -+ g_free (bdata->uri); -+ g_free (bdata->location); -+ g_free (bdata->info); -+ g_free (bdata->make_model); -+ g_free (bdata->browse_options); -+ g_free (bdata); -+} -+ -+static void -+prepare_browse_data (void) -+{ -+ static const char * const rattrs[] = { "printer-type", -+ "printer-state", -+ "printer-uri-supported", -+ "printer-info", -+ "printer-location", -+ "printer-make-and-model", -+ "auth-info-required", -+ "printer-uuid", -+ "job-template" }; -+ ipp_t *request, *response = NULL; -+ ipp_attribute_t *attr; -+ http_t *conn = NULL; -+ -+ conn = http_connect_local (); -+ -+ if (conn == NULL) { -+ debug_printf("cups-browsed: browse send failed to connect to localhost\n"); -+ goto fail; -+ } -+ -+ request = ippNewRequest(CUPS_GET_PRINTERS); -+ ippAddStrings (request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, -+ "requested-attributes", sizeof (rattrs) / sizeof (rattrs[0]), -+ NULL, rattrs); -+ ippAddString (request, IPP_TAG_OPERATION, IPP_TAG_NAME, -+ "requesting-user-name", NULL, cupsUser ()); -+ -+ debug_printf("cups-browsed: preparing browse data\n"); -+ response = cupsDoRequest (conn, request, "/"); -+ if (cupsLastError() > IPP_OK_CONFLICT) { -+ debug_printf("cups-browsed: browse send failed for localhost: %s\n", -+ cupsLastErrorString ()); -+ goto fail; -+ } -+ -+ g_list_free_full (browse_data, browse_data_free); -+ browse_data = NULL; -+ for (attr = ippFirstAttribute(response); attr; -+ attr = ippNextAttribute(response)) { -+ int type = -1, state = -1; -+ const char *uri = NULL; -+ gchar *location = NULL; -+ gchar *info = NULL; -+ gchar *make_model = NULL; -+ GString *browse_options = g_string_new (""); -+ -+ /* Skip any non-printer attributes */ -+ while (attr && ippGetGroupTag(attr) != IPP_TAG_PRINTER) -+ attr = ippNextAttribute(response); -+ -+ if (!attr) -+ break; -+ -+ while (attr && ippGetGroupTag(attr) == IPP_TAG_PRINTER) { -+ const char *attrname = ippGetName(attr); -+ int value_tag = ippGetValueTag(attr); -+ -+ if (!strcasecmp(attrname, "printer-type") && -+ value_tag == IPP_TAG_ENUM) { -+ type = ippGetInteger(attr, 0); -+ if (type & CUPS_PRINTER_NOT_SHARED) { -+ /* Skip CUPS queues not marked as shared */ -+ state = -1; -+ type = -1; -+ break; -+ } -+ } else if (!strcasecmp(attrname, "printer-state") && -+ value_tag == IPP_TAG_ENUM) -+ state = ippGetInteger(attr, 0); -+ else if (!strcasecmp(attrname, "printer-uri-supported") && -+ value_tag == IPP_TAG_URI) -+ uri = ippGetString(attr, 0, NULL); -+ else if (!strcasecmp(attrname, "printer-location") && -+ value_tag == IPP_TAG_TEXT) { -+ /* Remove quotes */ -+ gchar **tokens = g_strsplit (ippGetString(attr, 0, NULL), "\"", -1); -+ location = g_strjoinv ("", tokens); -+ g_strfreev (tokens); -+ } else if (!strcasecmp(attrname, "printer-info") && -+ value_tag == IPP_TAG_TEXT) { -+ /* Remove quotes */ -+ gchar **tokens = g_strsplit (ippGetString(attr, 0, NULL), "\"", -1); -+ info = g_strjoinv ("", tokens); -+ g_strfreev (tokens); -+ } else if (!strcasecmp(attrname, "printer-make-and-model") && -+ value_tag == IPP_TAG_TEXT) { -+ /* Remove quotes */ -+ gchar **tokens = g_strsplit (ippGetString(attr, 0, NULL), "\"", -1); -+ make_model = g_strjoinv ("", tokens); -+ g_strfreev (tokens); -+ } else if (!strcasecmp(attrname, "auth-info-required") && -+ value_tag == IPP_TAG_KEYWORD) { -+ if (strcasecmp (ippGetString(attr, 0, NULL), "none")) -+ g_string_append_printf (browse_options, "auth-info-required=%s ", -+ ippGetString(attr, 0, NULL)); -+ } else if (!strcasecmp(attrname, "printer-uuid") && -+ value_tag == IPP_TAG_URI) -+ g_string_append_printf (browse_options, "uuid=%s ", -+ ippGetString(attr, 0, NULL)); -+ else if (!strcasecmp(attrname, "job-sheets-default") && -+ value_tag == IPP_TAG_NAME && -+ ippGetCount(attr) == 2) -+ g_string_append_printf (browse_options, "job-sheets=%s,%s ", -+ ippGetString(attr, 0, NULL), -+ ippGetString(attr, 1, NULL)); -+ else if (strstr(attrname, "-default")) { -+ gchar *name = g_strdup (attrname); -+ gchar *value = NULL; -+ *strstr (name, "-default") = '\0'; -+ -+ switch (value_tag) { -+ gchar **tokens; -+ -+ case IPP_TAG_KEYWORD: -+ case IPP_TAG_STRING: -+ case IPP_TAG_NAME: -+ /* Escape value */ -+ tokens = g_strsplit_set (ippGetString(attr, 0, NULL), -+ " \"\'\\", -1); -+ value = g_strjoinv ("\\", tokens); -+ g_strfreev (tokens); -+ break; -+ -+ default: -+ /* other values aren't needed? */ -+ debug_printf("cups-browsed: skipping %s (%d)\n", name, value_tag); -+ break; -+ } -+ -+ if (value) { -+ g_string_append_printf (browse_options, "%s=%s ", name, value); -+ g_free (value); -+ } -+ -+ g_free (name); -+ } -+ -+ attr = ippNextAttribute(response); -+ } -+ -+ if (type != -1 && state != -1 && uri && location && info && make_model) { -+ gchar *browse_options_str = g_string_free (browse_options, FALSE); -+ browse_data_t *data; -+ browse_options = NULL; -+ g_strchomp (browse_options_str); -+ data = new_browse_data (type, state, uri, location, -+ info, make_model, browse_options_str); -+ browse_data = g_list_insert (browse_data, data, 0); -+ g_free (browse_options_str); -+ } -+ -+ if (make_model) -+ g_free (make_model); -+ -+ if (info) -+ g_free (info); -+ -+ if (location) -+ g_free (location); -+ -+ if (browse_options) -+ g_string_free (browse_options, TRUE); -+ -+ if (!attr) -+ break; -+ } -+ -+ fail: -+ if (response) -+ ippDelete(response); -+} -+ -+static void -+update_local_printers (void) -+{ -+ gboolean get_printers = FALSE; -+ http_t *conn; -+ -+ if (inhibit_local_printers_update) -+ return; -+ -+ conn = http_connect_local (); -+ if (conn && -+ (!local_printers_context || local_printers_context->can_subscribe)) { -+ if (!local_printers_context || -+ local_printers_context->subscription_id == -1) { -+ /* No subscription yet. First, create the subscription. */ -+ local_printers_create_subscription (conn); -+ get_printers = TRUE; -+ } else -+ /* We already have a subscription, so use it. */ -+ -+ /* Note: for the moment, browse_poll_get_notifications() just -+ * tells us whether we should re-fetch the printer list, so it -+ * is safe to use here. */ -+ get_printers = browse_poll_get_notifications (local_printers_context, -+ conn); -+ } else -+ get_printers = TRUE; -+ -+ if (get_printers) { -+ get_local_printers (); -+ -+ if (BrowseLocalProtocols & BROWSE_CUPS) -+ prepare_browse_data (); -+ } -+} -+ -+gboolean -+autoshutdown_execute (gpointer data) -+{ -+ /* Are we still in auto shutdown mode and are we still without queues */ -+ if (autoshutdown && cupsArrayCount(remote_printers) == 0) { -+ debug_printf("cups-browsed: Automatic shutdown as there are no print queues maintained by us for %d sec.\n", -+ autoshutdown_timeout); -+ g_main_loop_quit(gmainloop); -+ } -+ -+ /* Stop this timeout handler, we needed it only once */ -+ return FALSE; -+} -+ - static remote_printer_t * - create_local_queue (const char *name, - const char *uri, - const char *host, - const char *info, - const char *type, -- const char *domain) -+ const char *domain, -+ const char *pdl, -+ const char *make_model, -+ int is_cups_queue) - { - remote_printer_t *p; - remote_printer_t *q; -+ int fd = 0; /* Script file descriptor */ -+ char tempfile[1024]; /* Temporary file */ -+ char buffer[8192]; /* Buffer for creating script */ -+ int bytes; -+ const char *cups_serverbin; /* CUPS_SERVERBIN environment variable */ -+#if 0 -+ int i, uri_status, port, status; -+ http_t *http; -+ char scheme[10], userpass[1024], host_name[1024], resource[1024]; -+ ipp_t *request, *response; -+ ipp_attribute_t *attr; -+ static const char * const requested_attrs[] = -+ { /* Requested attributes for getting IPP network printer capabilities */ -+ /* Explicit attribute listings for the case that "all" does not cover -+ everything */ -+ "job-template", -+ "printer-description", -+ /*"document-format-supported", -+ "color-supported", -+ "pages-per-minute", -+ "pages-per-minute-color", -+ "media-supported", -+ "media-ready", -+ "media-default", -+ "media-type-supported", -+ "media-source-supported",*/ -+ "media-col-database", -+ /*"sides-supported", -+ "sides-default", -+ "output-bin-supported", -+ "output-bin-default", -+ "finishings-supported", -+ "finishings-default", -+ "print-color-mode-supported", -+ "print-color-mode-default", -+ "output-mode-supported", -+ "output-mode-default", -+ "print-quality-supported", -+ "print-quality-default", -+ "printer-resolution-supported", -+ "printer-resolution-default", -+ "copies-supported", -+ "copies-default",*/ -+ /* Catch things which were forgotten above or newly introduced */ -+ "all" -+ }; -+ static int versions_to_try[] = -+ { -+ 20, -+ 11 -+ }; -+#endif /* 0 */ - - /* Mark this as a queue to be created locally pointing to the printer */ - if ((p = (remote_printer_t *)calloc(1, sizeof(remote_printer_t))) == NULL) { -@@ -264,39 +745,219 @@ create_local_queue (const char *name, - goto fail; - - p->domain = strdup (domain); -- if (!p->domain) { -- fail: -- debug_printf("cups-browsed: ERROR: Unable to allocate memory.\n"); -- free (p->type); -- free (p->service_name); -- free (p->host); -- free (p->uri); -- free (p->name); -- free (p); -- return NULL; -- } -+ if (!p->domain) -+ goto fail; - - /* Schedule for immediate creation of the CUPS queue */ - p->status = STATUS_TO_BE_CREATED; - p->timeout = time(NULL) + TIMEOUT_IMMEDIATELY; - -- /* Check whether we have an equally named queue already from another -- server */ -- for (q = (remote_printer_t *)cupsArrayFirst(remote_printers); -- q; -- q = (remote_printer_t *)cupsArrayNext(remote_printers)) -- if (!strcmp(q->name, p->name)) -- break; -- p->duplicate = q ? 1 : 0; -+ if (is_cups_queue) { -+ /* Our local queue must be raw, so that the PPD file and driver -+ on the remote CUPS server get used */ -+ p->ppd = NULL; -+ p->model = NULL; -+ p->ifscript = NULL; -+ /* Check whether we have an equally named queue already from another -+ server */ -+ for (q = (remote_printer_t *)cupsArrayFirst(remote_printers); -+ q; -+ q = (remote_printer_t *)cupsArrayNext(remote_printers)) -+ if (!strcasecmp(q->name, p->name)) -+ break; -+ p->duplicate = (q && q->status != STATUS_DISAPPEARED && -+ q->status != STATUS_UNCONFIRMED) ? 1 : 0; -+ if (p->duplicate) -+ debug_printf("cups-browsed: Printer %s already available through host %s.\n", -+ p->name, q->host); -+ else if (q) { -+ q->duplicate = 1; -+ 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); -+ } -+ } else { -+ /* Non-CUPS printer broadcasts are most probably from printers -+ directly connected to the network and using the IPP protocol. -+ We check whether we can set them up without a device-specific -+ driver, only using page description languages which the -+ operating system provides: PCL 5c/5e/6/XL, PostScript, PDF, PWG -+ Raster. Especially IPP Everywhere printers and PDF-capable -+ AirPrint printers will work this way. Making only driverless -+ queues we can get an easy, configuration-less way to print -+ from mobile devices, even if there is no CUPS server with -+ shared printers around. */ -+ -+ if (CreateIPPPrinterQueues == 0) { -+ debug_printf("cups-browsed: Printer %s (%s) is an IPP network printer and cups-browsed id not configured to set up such printers automatically, ignoring this printer.\n", -+ p->name, p->uri); -+ goto fail; -+ } -+ -+ if (!pdl || pdl[0] == '\0' || (!strcasestr(pdl, "application/postscript") && !strcasestr(pdl, "application/pdf") && !strcasestr(pdl, "image/pwg-raster") && !strcasestr(pdl, "application/vnd.hp-PCL") && !strcasestr(pdl, "application/vnd.hp-PCLXL"))) { -+ debug_printf("cups-browsed: Cannot create remote printer %s (%s) as its PDLs are not known, ignoring this printer.\n", -+ p->name, p->uri); -+ goto fail; -+ } -+ -+#if 0 -+ uri_status = httpSeparateURI(HTTP_URI_CODING_ALL, uri, -+ scheme, sizeof(scheme), -+ userpass, sizeof(userpass), -+ host_name, sizeof(host_name), -+ &(port), -+ resource, sizeof(resource)); -+ if (uri_status != HTTP_URI_OK) -+ goto fail; -+ if ((http = httpConnect(host_name, port)) == -+ NULL) { -+ debug_printf("cups-browsed: Cannot connect to remote printer %s (%s:%d), ignoring this printer.\n", -+ p->uri, host_name, port); -+ goto fail; -+ } -+ for (i = 0; -+ i < sizeof(versions_to_try) / sizeof(versions_to_try[0]); -+ i ++) { -+ /* Create IPP request */ -+ request = ippNewRequest(IPP_GET_PRINTER_ATTRIBUTES); -+ /* Set IPP version */ -+ ippSetVersion(request, versions_to_try[i] / 10, versions_to_try[i] % 10); -+ /* Printer URI */ -+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, -+ "printer-uri", NULL, p->uri); -+ /* Requested IPP attributes */ -+ ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, -+ "requested-attributes", -+ sizeof(requested_attrs) / sizeof(requested_attrs[0]), -+ NULL, requested_attrs); -+ /* Do it */ -+ response = cupsDoRequest(http, request, resource); -+ if (response == NULL) { -+ debug_printf("cups-browsed: No answer to Get-Printer-Attributes IPP request from remote printer %s, ignoring this printer (IPP Error: %s %s).\n", -+ p->uri, ippErrorString(cupsLastError()), -+ cupsLastErrorString()); -+ httpClose(http); -+ goto fail; -+ } -+ status = cupsLastError(); -+ debug_printf("cups-browsed: Remote printer %s, IPP %3.1f: %s (%s)\n", -+ p->uri, versions_to_try[i] / 10.0, -+ ippErrorString(cupsLastError()), -+ cupsLastErrorString()); -+ /* If succeeded, go on, on error try a lower IPP version */ -+ if (status < 0x0400) -+ break; -+ } -+ if (i >= sizeof(versions_to_try) / sizeof(versions_to_try[0])) { -+ /* All IPP versions failed */ -+ debug_printf("cups-browsed: Remote printer %s: All IPP versions failed\n", -+ p->uri); -+ goto fail; -+ } -+ /* Read out the printer's capabilities */ -+ attr = ippFirstAttribute(response); -+ while (attr) { -+ debug_printf("Attr: %s\n", -+ ippGetName(attr)); -+ for (i = 0; i < ippGetCount(attr); i ++) -+ debug_printf("Keyword: %s\n", -+ ippGetString(attr, i, NULL)); -+ attr = ippNextAttribute(response); -+ } -+ attr = ippFindAttribute(response, -+ "document-format-supported", -+ IPP_TAG_ZERO); -+ if (attr) -+ for (i = 0; i < ippGetCount(attr); i ++) -+ debug_printf("Format: %s\n", -+ ippGetString(attr, i, NULL)); -+ else -+ debug_printf("No formats\n"); -+ -+ /* Clean up */ -+ ippDelete(response); -+ httpClose(http); -+#endif /* 0 */ -+ -+ p->duplicate = 0; -+ -+ /*p->model = "drv:///sample.drv/laserjet.ppd"; -+ debug_printf("cups-browsed: PPD from system for %s: %s\n", p->name, p->model);*/ -+ -+ /*p->ppd = "/usr/share/ppd/cupsfilters/pxlcolor.ppd"; -+ debug_printf("cups-browsed: PPD from file for %s: %s\n", p->name, p->ppd);*/ -+ -+ /*p->ifscript = "/usr/lib/cups/filter/pdftoippprinter-wrapper"; -+ debug_printf("cups-browsed: System V Interface script for %s: %s\n", p->name, p->ifscript);*/ -+ -+ if ((cups_serverbin = getenv("CUPS_SERVERBIN")) == NULL) -+ cups_serverbin = CUPS_SERVERBIN; -+ -+ if ((fd = cupsTempFd(tempfile, sizeof(tempfile))) < 0) { -+ debug_printf("Unable to create interface script file\n"); -+ goto fail; -+ } -+ -+ debug_printf("Creating temp script file \"%s\"\n", tempfile); -+ -+ snprintf(buffer, sizeof(buffer), -+ "#!/bin/sh\n" -+ "# System V interface script for printer %s generated by cups-browsed\n" -+ "\n" -+ "if [ $# -lt 5 -o $# -gt 6 ]; then\n" -+ " echo \"ERROR: $0 job-id user title copies options [file]\" >&2\n" -+ " exit 1\n" -+ "fi\n" -+ "\n" -+ "# Read from given file\n" -+ "if [ -n \"$6\" ]; then\n" -+ " exec \"$0\" \"$1\" \"$2\" \"$3\" \"$4\" \"$5\" < \"$6\"\n" -+ "fi\n" -+ "\n" -+ "extra_options=\"output-format=%s make-and-model=%s\"\n" -+ "\n" -+ "%s/filter/pdftoippprinter \"$1\" \"$2\" \"$3\" \"$4\" \"$5 $extra_options\"\n", -+ p->name, pdl, make_model, cups_serverbin); -+ -+ bytes = write(fd, buffer, strlen(buffer)); -+ if (bytes != strlen(buffer)) { -+ debug_printf("Unable to write interface script into the file\n"); -+ goto fail; -+ } -+ -+ close(fd); -+ -+ p->ppd = NULL; -+ p->model = NULL; -+ p->ifscript = strdup(tempfile); -+ } - - /* Add the new remote printer entry */ - cupsArrayAdd(remote_printers, p); - -- if (p->duplicate) -- debug_printf("cups-browsed: Printer already available through host %s.\n", -- q->host); -+ /* If auto shutdown is active we have perhaps scheduled a timer to shut down -+ due to not having queues any more to maintain, kill the timer now */ -+ if (autoshutdown && autoshutdown_exec_id && -+ cupsArrayCount(remote_printers) > 0) { -+ debug_printf ("cups-browsed: New printers there to make available, killing auto shutdown timer.\n"); -+ g_source_destroy(g_main_context_find_source_by_id(NULL, -+ autoshutdown_exec_id)); -+ autoshutdown_exec_id = 0; -+ } - - return p; -+ -+ fail: -+ debug_printf("cups-browsed: ERROR: Unable to create print queue, ignoring printer.\n"); -+ free (p->type); -+ free (p->service_name); -+ free (p->host); -+ free (p->uri); -+ free (p->name); -+ if (p->ppd) free (p->ppd); -+ if (p->model) free (p->model); -+ if (p->ifscript) free (p->ifscript); -+ free (p); -+ return NULL; - } - - /* -@@ -414,8 +1075,7 @@ gboolean handle_cups_queues(gpointer unu - - /* Remove the CUPS queue */ - if (!p->duplicate) { /* Duplicates do not have a CUPS queue */ -- if ((http = httpConnectEncrypt(cupsServer(), ippPort(), -- cupsEncryption())) == NULL) { -+ if ((http = http_connect_local ()) == NULL) { - debug_printf("cups-browsed: Unable to connect to CUPS!\n"); - p->timeout = current_time + TIMEOUT_RETRY; - break; -@@ -429,7 +1089,6 @@ gboolean handle_cups_queues(gpointer unu - if (num_jobs != 0) { /* error or jobs */ - debug_printf("cups-browsed: Queue has still jobs or CUPS error!\n"); - cupsFreeJobs(num_jobs, jobs); -- httpClose(http); - /* Schedule the removal of the queue for later */ - p->timeout = current_time + TIMEOUT_RETRY; - break; -@@ -454,7 +1113,7 @@ gboolean handle_cups_queues(gpointer unu - if (attr) { - for (; attr && ippGetGroupTag(attr) == IPP_TAG_PRINTER; - attr = ippNextAttribute(response)) { -- if (!strcmp(ippGetName(attr), "printer-name") && -+ if (!strcasecmp(ippGetName(attr), "printer-name") && - ippGetValueTag(attr) == IPP_TAG_NAME) { - default_printer_name = ippGetString(attr, 0, NULL); - break; -@@ -469,9 +1128,9 @@ gboolean handle_cups_queues(gpointer unu - !strcasecmp(default_printer_name, p->name)) { - /* Printer is currently the system's default printer, - do not remove it */ -- httpClose(http); - /* Schedule the removal of the queue for later */ - p->timeout = current_time + TIMEOUT_RETRY; -+ ippDelete(response); - break; - } - if (response) -@@ -492,10 +1151,8 @@ gboolean handle_cups_queues(gpointer unu - if (cupsLastError() > IPP_OK_CONFLICT) { - debug_printf("cups-browsed: Unable to remove CUPS queue!\n"); - p->timeout = current_time + TIMEOUT_RETRY; -- httpClose(http); - break; - } -- httpClose(http); - } - - /* CUPS queue removed, remove the list entry */ -@@ -506,7 +1163,22 @@ gboolean handle_cups_queues(gpointer unu - if (p->service_name) free (p->service_name); - if (p->type) free (p->type); - if (p->domain) free (p->domain); -+ if (p->ppd) free (p->ppd); -+ if (p->model) free (p->model); -+ if (p->ifscript) free (p->ifscript); - free(p); -+ p = NULL; -+ -+ /* If auto shutdown is active and all printers we have set up got removed -+ again, schedule the shutdown in autoshutdown_timeout seconds */ -+ if (autoshutdown && !autoshutdown_exec_id && -+ cupsArrayCount(remote_printers) == 0) { -+ debug_printf ("cups-browsed: No printers there any more to make available, shutting down in %d sec...\n", autoshutdown_timeout); -+ autoshutdown_exec_id = -+ g_timeout_add_seconds (autoshutdown_timeout, autoshutdown_execute, -+ NULL); -+ } -+ - break; - - /* Bonjour has reported a new remote printer, create a CUPS queue for it, -@@ -530,8 +1202,7 @@ gboolean handle_cups_queues(gpointer unu - p->name); - - /* Create a new CUPS queue or modify the existing queue */ -- if ((http = httpConnectEncrypt(cupsServer(), ippPort(), -- cupsEncryption())) == NULL) { -+ if ((http = http_connect_local ()) == NULL) { - debug_printf("cups-browsed: Unable to connect to CUPS!\n"); - p->timeout = current_time + TIMEOUT_RETRY; - break; -@@ -556,7 +1227,7 @@ gboolean handle_cups_queues(gpointer unu - num_options = cupsAddOption("device-uri", p->uri, - num_options, &options); - /* Option cups-browsed=true, marking that we have created this queue */ -- num_options = cupsAddOption("cups-browsed-default", "true", -+ num_options = cupsAddOption(CUPS_BROWSED_MARK "-default", "true", - num_options, &options); - /* Do not share a queue which serves only to point to a remote printer */ - num_options = cupsAddOption("printer-is-shared", "false", -@@ -568,16 +1239,34 @@ gboolean handle_cups_queues(gpointer unu - num_options = cupsAddOption("printer-location", p->host, - num_options, &options); - cupsEncodeOptions2(request, num_options, options, IPP_TAG_PRINTER); -+ /* PPD from system's CUPS installation */ -+ if (p->model) { -+ debug_printf("cups-browsed: Non-raw queue %s with system PPD: %s\n", p->name, p->model); -+ p->ppd = cupsGetServerPPD(http, p->model); -+ } - /* Do it */ -- ippDelete(cupsDoRequest(http, request, "/admin/")); -+ if (p->ppd) { -+ debug_printf("cups-browsed: Non-raw queue %s with PPD file: %s\n", p->name, p->ppd); -+ ippDelete(cupsDoFileRequest(http, request, "/admin/", p->ppd)); -+ if (p->model) { -+ unlink(p->ppd); -+ free(p->ppd); -+ p->ppd = NULL; -+ } -+ } else if (p->ifscript) { -+ debug_printf("cups-browsed: Non-raw queue %s with interface script: %s\n", p->name, p->ifscript); -+ ippDelete(cupsDoFileRequest(http, request, "/admin/", p->ifscript)); -+ unlink(p->ifscript); -+ free(p->ifscript); -+ p->ifscript = NULL; -+ } else -+ ippDelete(cupsDoRequest(http, request, "/admin/")); - cupsFreeOptions(num_options, options); - if (cupsLastError() > IPP_OK_CONFLICT) { - debug_printf("cups-browsed: Unable to create CUPS queue!\n"); - p->timeout = current_time + TIMEOUT_RETRY; -- httpClose(http); - break; - } -- httpClose(http); - - if (p->status == STATUS_BROWSE_PACKET_RECEIVED) { - p->status = STATUS_DISAPPEARED; -@@ -637,40 +1326,123 @@ recheck_timer (void) - } - } - --void generate_local_queue(const char *host, -- uint16_t port, -- char *resource, -- const char *name, -- const char *type, -- const char *domain) { -- char *remote_queue = NULL, *remote_host = NULL; -+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) { -+ -+ char uri[HTTP_MAX_URI]; -+ char *remote_queue = NULL, *remote_host = NULL, *pdl = NULL; -+#ifdef HAVE_AVAHI -+ char *fields[] = { "product", "usb_MDL", "ty", NULL }, **f; -+ AvahiStringList *entry = NULL; -+ char *key = NULL, *value = NULL; -+#endif /* HAVE_AVAHI */ - remote_printer_t *p; -+ local_printer_t *local_printer; - char *backup_queue_name = NULL, *local_queue_name = NULL; -- cups_dest_t *dests = NULL, *dest = NULL; -- int i, num_dests; -+ int is_cups_queue; - size_t hl = 0; -- const char *val = NULL; -+ gboolean create = TRUE; -+ - -- /* This is a remote CUPS queue, find queue name and host name */ -- if (strncasecmp(resource, "printers/", 9)) { -- debug_printf("cups-browsed: resource does not begin 'printers/'\n"); -- return; -- } -+ is_cups_queue = 0; -+ memset(uri, 0, sizeof(uri)); - -- remote_queue = remove_bad_chars(resource + 9, 0); -+ /* Determine the device URI of the remote printer */ -+ httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri) - 1, -+ (strcasestr(type, "_ipps") ? "ipps" : "ipp"), NULL, -+ host, port, "/%s", resource); - /* Find the remote host name. - * Used in constructing backup_queue_name, so need to sanitize. - * strdup() is called inside remove_bad_chars() and result is free()-able. - */ - remote_host = remove_bad_chars(host, 1); - hl = strlen(remote_host); -- if (hl > 6 && !strcmp(remote_host + strlen(remote_host) - 6, ".local")) -- remote_host[strlen(remote_host) - 6] = '\0'; -- if (hl > 7 && !strcmp(remote_host + strlen(remote_host) - 7, ".local.")) -- remote_host[strlen(remote_host) - 7] = '\0'; -- debug_printf("cups-browsed: Found CUPS queue: %s on host %s.\n", -- remote_queue, 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'; -+ -+ /* Check by the resource whether the discovered printer is a CUPS queue */ -+ if (!strncasecmp(resource, "printers/", 9)) { -+ /* This is a remote CUPS queue, use the remote queue name for the -+ local queue */ -+ is_cups_queue = 1; -+ /* Not directly used in script generation input later, but taken from -+ packet, so better safe than sorry. (consider second loop with -+ backup_queue_name) */ -+ remote_queue = remove_bad_chars(resource + 9, 0); -+ debug_printf("cups-browsed: Found CUPS queue: %s on host %s.\n", -+ remote_queue, remote_host); -+#ifdef HAVE_AVAHI -+ /* If the remote queue has a PPD file, the "product" field of the -+ TXT record is populated. If it has no PPD file the remote queue -+ is a raw queue and so we do not know enough about the printer -+ behind it for auto-creating a local queue pointing to it. */ -+ int raw_queue = 0; -+ if (txt) { -+ entry = avahi_string_list_find((AvahiStringList *)txt, "product"); -+ if (entry) { -+ avahi_string_list_get_pair(entry, &key, &value, NULL); -+ if (!key || !value || strcasecmp(key, "product") || value[0] != '(' || -+ value[strlen(value) - 1] != ')') { -+ raw_queue = 1; -+ } -+ } else -+ raw_queue = 1; -+ } else if (domain && domain[0] != '\0') -+ raw_queue = 1; -+ if (raw_queue) { -+ /* The remote CUPS queue is raw, ignore it */ -+ debug_printf("cups-browsed: Remote Bonjour-advertised CUPS queue %s on host %s is raw, ignored.\n", -+ remote_queue, remote_host); -+ free (remote_host); -+ return NULL; -+ } -+#endif /* HAVE_AVAHI */ -+ } else if (!strncasecmp(resource, "classes/", 8)) { -+ /* This is a remote CUPS queue, use the remote queue name for the -+ local queue */ -+ is_cups_queue = 1; -+ /* Not directly used in script generation input later, but taken from -+ packet, so better safe than sorry. (consider second loop with -+ backup_queue_name) */ -+ remote_queue = remove_bad_chars(resource + 8, 0); -+ debug_printf("cups-browsed: Found CUPS queue: %s on host %s.\n", -+ remote_queue, remote_host); -+ } else { -+ /* This is an IPP-based network printer */ -+ is_cups_queue = 0; -+ /* Determine the queue name by the model */ -+ remote_queue = strdup("printer"); -+#ifdef HAVE_AVAHI -+ if (txt) { -+ for (f = fields; *f; f ++) { -+ entry = avahi_string_list_find((AvahiStringList *)txt, *f); -+ if (entry) { -+ avahi_string_list_get_pair(entry, &key, &value, NULL); -+ if (key && value && !strcasecmp(key, *f) && strlen(value) >= 3) { -+ remote_queue = remove_bad_chars(value, 0); -+ break; -+ } -+ } -+ } -+ /* Find out which PDLs the printer understands */ -+ entry = avahi_string_list_find((AvahiStringList *)txt, "pdl"); -+ if (entry) { -+ avahi_string_list_get_pair(entry, &key, &value, NULL); -+ if (key && value && !strcasecmp(key, "pdl") && strlen(value) >= 3) { -+ pdl = remove_bad_chars(value, 1); -+ } -+ } -+ } -+#endif /* HAVE_AVAHI */ -+ } - /* Check if there exists already a CUPS queue with the - requested name Try name@host in such a case and if - this is also taken, ignore the printer */ -@@ -683,136 +1455,150 @@ void generate_local_queue(const char *ho - sprintf(backup_queue_name, "%s@%s", remote_queue, remote_host); - - /* Get available CUPS queues */ -- num_dests = cupsGetDests(&dests); -+ update_local_printers (); - - local_queue_name = remote_queue; -- if (num_dests > 0) { -+ -+ /* Is there a local queue with the same URI as the remote queue? */ -+ if (g_hash_table_find (local_printers, -+ local_printer_has_uri, -+ uri)) -+ create = FALSE; -+ -+ if (create) { - /* Is there a local queue with the name of the remote queue? */ -- for (i = num_dests, dest = dests; i > 0; i --, dest ++) -+ local_printer = g_hash_table_lookup (local_printers, -+ local_queue_name); - /* Only consider CUPS queues not created by us */ -- if ((((val = -- cupsGetOption(CUPS_BROWSED_MARK, dest->num_options, -- dest->options)) == NULL) || -- (strcasecmp(val, "yes") != 0 && -- strcasecmp(val, "on") != 0 && -- strcasecmp(val, "true") != 0)) && -- !strcmp(local_queue_name, dest->name)) -- break; -- if (i > 0) { -+ if (local_printer && !local_printer->cups_browsed_controlled) { - /* Found local queue with same name as remote queue */ - /* Is there a local queue with the name @? */ - local_queue_name = backup_queue_name; - debug_printf("cups-browsed: %s already taken, using fallback name: %s\n", - remote_queue, local_queue_name); -- for (i = num_dests, dest = dests; i > 0; i --, dest ++) -- /* Only consider CUPS queues not created by us */ -- if ((((val = -- cupsGetOption(CUPS_BROWSED_MARK, dest->num_options, -- dest->options)) == NULL) || -- (strcasecmp(val, "yes") != 0 && -- strcasecmp(val, "on") != 0 && -- strcasecmp(val, "true") != 0)) && -- !strcmp(local_queue_name, dest->name)) -- break; -- if (i > 0) { -+ local_printer = g_hash_table_lookup (local_printers, -+ local_queue_name); -+ if (local_printer && !local_printer->cups_browsed_controlled) { - /* Found also a local queue with name @, so - ignore this remote printer */ - debug_printf("cups-browsed: %s also taken, printer ignored.\n", - local_queue_name); - free (backup_queue_name); - free (remote_host); -+ free (pdl); - free (remote_queue); -- cupsFreeDests(num_dests, dests); -- return; -+ return NULL; - } - } -- cupsFreeDests(num_dests, dests); - } - - /* Check if we have already created a queue for the discovered - printer */ - for (p = (remote_printer_t *)cupsArrayFirst(remote_printers); - p; p = (remote_printer_t *)cupsArrayNext(remote_printers)) -- if (!strcmp(p->name, local_queue_name) && -+ if (!strcasecmp(p->name, local_queue_name) && - (p->host[0] == '\0' || -- !strcmp(p->host, remote_host))) -+ p->status == STATUS_UNCONFIRMED || -+ p->status == STATUS_DISAPPEARED || -+ !strcasecmp(p->host, remote_host))) - break; - -+ if (!create) { -+ free (remote_host); -+ free (backup_queue_name); -+ free (pdl); -+ free (remote_queue); -+ if (p) { -+ return p; -+ } else { -+ /* Found a local queue with the same URI as our discovered printer -+ would get, so ignore this remote printer */ -+ debug_printf("cups-browsed: Printer with URI %s already exists, printer ignored.\n", -+ uri); -+ return NULL; -+ } -+ } -+ - if (p) { - /* We have already created a local queue, check whether the -- discovered service allows us to upgrade the queue to IPPS */ -- if (strcasestr(type, "_ipps") && -- !strncmp(p->uri, "ipp:", 4)) { -- -- /* Schedule local queue for upgrade to ipps: */ -- if ((p->uri = realloc(p->uri, strlen(p->uri) + 2)) == NULL){ -- debug_printf("cups-browsed: ERROR: Unable to allocate memory.\n"); -- exit(1); -- } -- memmove((void *)(p->uri + 4), (const void *)(p->uri + 3), -- strlen(p->uri) - 2); -- p->uri[3] = 's'; -+ discovered service allows us to upgrade the queue to IPPS -+ or whether the URI part after ipp(s):// has changed */ -+ if ((strcasestr(type, "_ipps") && -+ !strncasecmp(p->uri, "ipp:", 4)) || -+ strcasecmp(strchr(p->uri, ':'), strchr(uri, ':'))) { -+ -+ /* Schedule local queue for upgrade to ipps: or for URI change */ -+ if (strcasestr(type, "_ipps") && -+ !strncasecmp(p->uri, "ipp:", 4)) -+ debug_printf("cups-browsed: Upgrading printer %s (Host: %s) to IPPS. New URI: %s\n", -+ p->name, remote_host, uri); -+ if (strcasecmp(strchr(p->uri, ':'), strchr(uri, ':'))) -+ debug_printf("cups-browsed: Changing URI of printer %s (Host: %s) to %s.\n", -+ p->name, remote_host, uri); -+ free(p->uri); -+ free(p->host); -+ free(p->service_name); -+ free(p->type); -+ free(p->domain); -+ p->uri = strdup(uri); - p->status = STATUS_TO_BE_CREATED; - p->timeout = time(NULL) + TIMEOUT_IMMEDIATELY; - p->host = strdup(remote_host); - p->service_name = strdup(name); - p->type = strdup(type); - p->domain = strdup(domain); -- debug_printf("cups-browsed: Upgrading printer %s (Host: %s) to IPPS. New URI: %s\n", -- p->name, p->host, p->uri); - - } else { - - /* Nothing to do, mark queue entry as confirmed if the entry - is unconfirmed */ -- debug_printf("cups-browsed: Entry for %s (Host: %s, URI: %s) already exists.\n", -- p->name, p->host, p->uri); -- if (p->status == STATUS_UNCONFIRMED) { -+ debug_printf("cups-browsed: Entry for %s (URI: %s) already exists.\n", -+ p->name, p->uri); -+ if (p->status == STATUS_UNCONFIRMED || -+ p->status == STATUS_DISAPPEARED) { - p->status = STATUS_CONFIRMED; - p->timeout = (time_t) -1; -- debug_printf("cups-browsed: Marking entry for %s (Host: %s, URI: %s) as confirmed.\n", -- p->name, p->host, p->uri); -+ debug_printf("cups-browsed: Marking entry for %s (URI: %s) as confirmed.\n", -+ p->name, p->uri); - } - - } -- if (p->host[0] == '\0') -+ if (p->host[0] == '\0') { -+ free (p->host); - p->host = strdup(remote_host); -- if (p->service_name[0] == '\0' && name) -+ } -+ if (p->service_name[0] == '\0' && name) { -+ free (p->service_name); - p->service_name = strdup(name); -- if (p->type[0] == '\0' && type) -+ } -+ if (p->type[0] == '\0' && type) { -+ free (p->type); - p->type = strdup(type); -- if (p->domain[0] == '\0' && domain) -+ } -+ if (p->domain[0] == '\0' && domain) { -+ free (p->domain); - p->domain = strdup(domain); -- -+ } - } else { - - /* We need to create a local queue pointing to the - discovered printer */ -- -- /* Device URI: ipp(s)://:631/printers/ */ -- char *uri = malloc(strlen(host) + -- strlen(remote_queue) + 34); -- if (uri == NULL) { -- debug_printf("cups-browsed: ERROR: Unable to allocate memory.\n"); -- exit(1); -- } -- sprintf(uri, "ipp%s://%s:%u/printers/%s", -- (strcasestr(type, "_ipps") ? "s" : ""), host, -- port, remote_queue); -- - p = create_local_queue (local_queue_name, uri, remote_host, -- name ? name : "", type, domain); -- free (uri); -+ name ? name : "", type, domain, pdl, remote_queue, -+ is_cups_queue); - } - - free (backup_queue_name); - free (remote_host); -+ free (pdl); - free (remote_queue); - - if (p) - debug_printf("cups-browsed: Bonjour IDs: Service name: \"%s\", " - "Service type: \"%s\", Domain: \"%s\"\n", - p->service_name, p->type, p->domain); -+ -+ return p; - } - - #ifdef HAVE_AVAHI -@@ -852,30 +1638,47 @@ static void resolve_callback( - debug_printf("cups-browsed: Avahi Resolver: Service '%s' of type '%s' in domain '%s'.\n", - name, type, domain); - -- /* Check if we have a remote CUPS queue, other remote printers are not -- handled by us */ - rp_entry = avahi_string_list_find(txt, "rp"); -- adminurl_entry = avahi_string_list_find(txt, "adminurl"); -- if (rp_entry && adminurl_entry) { -+ if (rp_entry) - avahi_string_list_get_pair(rp_entry, &rp_key, &rp_value, NULL); -+ else { -+ rp_key = strdup("rp"); -+ rp_value = strdup(""); -+ } -+ adminurl_entry = avahi_string_list_find(txt, "adminurl"); -+ if (adminurl_entry) - avahi_string_list_get_pair(adminurl_entry, &adminurl_key, - &adminurl_value, NULL); -+ else { -+ adminurl_key = strdup("adminurl"); -+ if ((adminurl_value = malloc(strlen(host_name) + 8)) != NULL) -+ sprintf(adminurl_value, "http://%s", host_name); -+ else -+ adminurl_value = strdup(""); -+ } - -- /* Check by "rp" and "adminurl" TXT record fields whether -- the discovered printer is a CUPS queue */ -- if (rp_key && rp_value && adminurl_key && adminurl_value && -- !strcmp(rp_key, "rp") && !strncmp(rp_value, "printers/", 9) && -- !strcmp(adminurl_key, "adminurl") && -- !strcmp(adminurl_value + strlen(adminurl_value) - -- strlen(rp_value), rp_value)) { -- generate_local_queue(host_name, port, rp_value, name, type, domain); -- } -+ if (rp_key && rp_value && adminurl_key && adminurl_value && -+ !strcasecmp(rp_key, "rp") && !strcasecmp(adminurl_key, "adminurl")) { -+ /* Check remote printer type and create appropriate local queue to -+ point to it */ -+ generate_local_queue(host_name, port, rp_value, name, type, domain, txt); -+ } -+ -+ /* Clean up */ - -- /* Clean up */ -+ if (rp_entry) { - avahi_free(rp_key); - avahi_free(rp_value); -+ } else { -+ free(rp_key); -+ free(rp_value); -+ } -+ if (adminurl_entry) { - avahi_free(adminurl_key); - avahi_free(adminurl_value); -+ } else { -+ free(adminurl_key); -+ free(adminurl_value); - } - break; - } -@@ -905,7 +1708,7 @@ static void browse_callback( - - switch (event) { - -- /* Avah browser error */ -+ /* Avahi browser error */ - case AVAHI_BROWSER_FAILURE: - - debug_printf("cups-browsed: Avahi Browser: ERROR: %s\n", -@@ -947,9 +1750,9 @@ static void browse_callback( - /* Check whether we have listed this printer */ - for (p = (remote_printer_t *)cupsArrayFirst(remote_printers); - p; p = (remote_printer_t *)cupsArrayNext(remote_printers)) -- if (!strcmp(p->service_name, name) && -- !strcmp(p->type, type) && -- !strcmp(p->domain, domain)) -+ if (!strcasecmp(p->service_name, name) && -+ !strcasecmp(p->type, type) && -+ !strcasecmp(p->domain, domain)) - break; - if (p) { - /* Check whether this queue has a duplicate from another server */ -@@ -958,8 +1761,8 @@ static void browse_callback( - for (q = (remote_printer_t *)cupsArrayFirst(remote_printers); - q; - q = (remote_printer_t *)cupsArrayNext(remote_printers)) -- if (!strcmp(q->name, p->name) && -- strcmp(q->host, p->host) && -+ if (!strcasecmp(q->name, p->name) && -+ strcasecmp(q->host, p->host) && - q->duplicate) - break; - } -@@ -970,16 +1773,22 @@ static void browse_callback( - free (p->service_name); - free (p->type); - free (p->domain); -+ if (p->ppd) free (p->ppd); -+ if (p->model) free (p->model); -+ if (p->ifscript) free (p->ifscript); - /* Replace the data with the data of the duplicate printer */ - p->uri = strdup(q->uri); - p->host = strdup(q->host); - p->service_name = strdup(q->service_name); - p->type = strdup(q->type); - p->domain = strdup(q->domain); -+ if (q->ppd) p->ppd = strdup(q->ppd); -+ if (q->model) p->model = strdup(q->model); -+ if (q->ifscript) p->ifscript = strdup(q->ifscript); - /* Schedule this printer for updating the CUPS queue */ - p->status = STATUS_TO_BE_CREATED; - p->timeout = time(NULL) + TIMEOUT_IMMEDIATELY; -- /* Schedule the remote printer for removal */ -+ /* Schedule the duplicate printer entry for removal */ - q->status = STATUS_DISAPPEARED; - q->timeout = time(NULL) + TIMEOUT_IMMEDIATELY; - -@@ -1015,20 +1824,171 @@ static void browse_callback( - - } - -+void avahi_browser_shutdown() { -+ remote_printer_t *p; -+ -+ /* Remove all queues which we have set up based on Bonjour discovery*/ -+ for (p = (remote_printer_t *)cupsArrayFirst(remote_printers); -+ p; p = (remote_printer_t *)cupsArrayNext(remote_printers)) { -+ if (p->type && p->type[0]) { -+ p->status = STATUS_DISAPPEARED; -+ p->timeout = time(NULL) + TIMEOUT_IMMEDIATELY; -+ } -+ } -+ handle_cups_queues(NULL); -+ -+ /* Free the data structures for Bonjour browsing */ -+ if (sb1) { -+ avahi_service_browser_free(sb1); -+ sb1 = NULL; -+ } -+ if (sb2) { -+ avahi_service_browser_free(sb2); -+ sb2 = NULL; -+ } -+ -+ /* Switch on auto shutdown mode */ -+ if (autoshutdown_avahi) { -+ autoshutdown = 1; -+ debug_printf("cups-browsed: Avahi server disappeared, switching to auto shutdown mode ...\n"); -+ /* If there are no printers schedule the shutdown in autoshutdown_timeout -+ seconds */ -+ if (!autoshutdown_exec_id && -+ cupsArrayCount(remote_printers) == 0) { -+ debug_printf ("cups-browsed: We entered auto shutdown mode and no printers are there to make available, shutting down in %d sec...\n", autoshutdown_timeout); -+ autoshutdown_exec_id = -+ g_timeout_add_seconds (autoshutdown_timeout, autoshutdown_execute, -+ NULL); -+ } -+ } -+} -+ -+void avahi_shutdown() { -+ avahi_browser_shutdown(); -+ if (client) { -+ avahi_client_free(client); -+ client = NULL; -+ } -+ if (glib_poll) { -+ avahi_glib_poll_free(glib_poll); -+ glib_poll = NULL; -+ } -+} -+ - static void client_callback(AvahiClient *c, AvahiClientState state, AVAHI_GCC_UNUSED void * userdata) { -+ int error; -+ - assert(c); - - /* Called whenever the client or server state changes */ -+ switch (state) { - -- if (state == AVAHI_CLIENT_FAILURE) { -- debug_printf("cups-browsed: ERROR: Avahi server connection failure: %s\n", -- avahi_strerror(avahi_client_errno(c))); -- g_main_loop_quit(gmainloop); -+ /* avahi-daemon available */ -+ case AVAHI_CLIENT_S_REGISTERING: -+ case AVAHI_CLIENT_S_RUNNING: -+ case AVAHI_CLIENT_S_COLLISION: -+ -+ debug_printf("cups-browsed: Avahi server connection got available, setting up service browsers.\n"); -+ -+ /* Create the service browsers */ -+ if (!sb1) -+ if (!(sb1 = -+ avahi_service_browser_new(c, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, -+ "_ipp._tcp", NULL, 0, browse_callback, -+ c))) { -+ debug_printf("cups-browsed: ERROR: Failed to create service browser for IPP: %s\n", -+ avahi_strerror(avahi_client_errno(c))); -+ } -+ if (!sb2) -+ if (!(sb2 = -+ avahi_service_browser_new(c, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, -+ "_ipps._tcp", NULL, 0, browse_callback, -+ c))) { -+ debug_printf("cups-browsed: ERROR: Failed to create service browser for IPPS: %s\n", -+ avahi_strerror(avahi_client_errno(c))); -+ } -+ -+ /* switch off auto shutdown mode */ -+ if (autoshutdown_avahi) { -+ autoshutdown = 0; -+ debug_printf("cups-browsed: Avahi server available, switching to permanent mode ...\n"); -+ /* If there is still an active auto shutdown timer, kill it */ -+ if (autoshutdown_exec_id > 0) { -+ debug_printf ("cups-browsed: We have left auto shutdown mode, killing auto shutdown timer.\n"); -+ g_source_destroy(g_main_context_find_source_by_id(NULL, -+ autoshutdown_exec_id)); -+ autoshutdown_exec_id = 0; -+ } -+ } -+ -+ break; -+ -+ /* Avahi client error */ -+ case AVAHI_CLIENT_FAILURE: -+ -+ if (avahi_client_errno(c) == AVAHI_ERR_DISCONNECTED) { -+ debug_printf("cups-browsed: Avahi server disappeared, shutting down service browsers, removing Bonjour-discovered print queues.\n"); -+ avahi_browser_shutdown(); -+ /* Renewing client */ -+ avahi_client_free(client); -+ client = avahi_client_new(avahi_glib_poll_get(glib_poll), -+ AVAHI_CLIENT_NO_FAIL, -+ client_callback, NULL, &error); -+ if (!client) { -+ debug_printf("cups-browsed: ERROR: Failed to create client: %s\n", -+ avahi_strerror(error)); -+ BrowseRemoteProtocols &= ~BROWSE_DNSSD; -+ avahi_shutdown(); -+ } -+ } else { -+ debug_printf("cups-browsed: ERROR: Avahi server connection failure: %s\n", -+ avahi_strerror(avahi_client_errno(c))); -+ g_main_loop_quit(gmainloop); -+ } -+ break; -+ -+ default: -+ break; - } -+} -+ -+void avahi_init() { -+ int error; -+ -+ if (BrowseRemoteProtocols & BROWSE_DNSSD) { -+ /* Allocate main loop object */ -+ if (!glib_poll) -+ if (!(glib_poll = avahi_glib_poll_new(NULL, G_PRIORITY_DEFAULT))) { -+ debug_printf("cups-browsed: ERROR: Failed to create glib poll object.\n"); -+ goto avahi_init_fail; -+ } -+ -+ /* Allocate a new client */ -+ if (!client) -+ client = avahi_client_new(avahi_glib_poll_get(glib_poll), -+ AVAHI_CLIENT_NO_FAIL, -+ client_callback, NULL, &error); - -+ /* Check wether creating the client object succeeded */ -+ if (!client) { -+ debug_printf("cups-browsed: ERROR: Failed to create client: %s\n", -+ avahi_strerror(error)); -+ goto avahi_init_fail; -+ } -+ -+ return; -+ -+ avahi_init_fail: -+ BrowseRemoteProtocols &= ~BROWSE_DNSSD; -+ avahi_shutdown(); -+ } - } - #endif /* HAVE_AVAHI */ - -+/* -+ * A CUPS printer has been discovered via CUPS Browsing -+ * or with BrowsePoll -+ */ - void - found_cups_printer (const char *remote_host, const char *uri, - const char *info) -@@ -1041,6 +2001,7 @@ found_cups_printer (const char *remote_h - netif_t *iface; - char local_resource[HTTP_MAX_URI]; - char *c; -+ remote_printer_t *printer; - - memset(scheme, 0, sizeof(scheme)); - memset(username, 0, sizeof(username)); -@@ -1059,7 +2020,7 @@ found_cups_printer (const char *remote_h - for (iface = cupsArrayFirst (netifs); - iface; - iface = cupsArrayNext (netifs)) -- if (!strcmp (host, iface->address)) -+ if (!strcasecmp (host, iface->address)) - break; - if (iface) { - debug_printf("cups-browsed: ignoring own broadcast on %s\n", -@@ -1067,7 +2028,8 @@ found_cups_printer (const char *remote_h - return; - } - -- if (strncmp (resource, "/printers/", 10)) { -+ if (strncasecmp (resource, "/printers/", 10) && -+ strncasecmp (resource, "/classes/", 9)) { - debug_printf("cups-browsed: don't understand URI: %s\n", uri); - return; - } -@@ -1081,15 +2043,26 @@ found_cups_printer (const char *remote_h - debug_printf("cups-browsed: browsed queue name is %s\n", - local_resource + 9); - -- generate_local_queue(host, port, local_resource, info ? info : "", "", ""); -+ printer = generate_local_queue(host, port, local_resource, -+ info ? info : "", -+ "", "", NULL); -+ -+ if (printer) { -+ if (printer->status == STATUS_TO_BE_CREATED) -+ printer->status = STATUS_BROWSE_PACKET_RECEIVED; -+ else { -+ printer->status = STATUS_DISAPPEARED; -+ printer->timeout = time(NULL) + BrowseTimeout; -+ } -+ } - } - - static gboolean - allowed (struct sockaddr *srcaddr) - { - allow_t *allow; -- if (cupsArrayCount(browseallow) == 0) { -- /* No "BrowseAllow" line, allow all servers */ -+ if (browseallow_all || cupsArrayCount(browseallow) == 0) { -+ /* "BrowseAllow All", or no "BrowseAllow" line, so allow all servers */ - return TRUE; - } - for (allow = cupsArrayFirst (browseallow); -@@ -1237,7 +2210,9 @@ process_browse_data (GIOChannel *source, - if (c >= end) - return TRUE; - -- found_cups_printer (remote_host, uri, info); -+ if (!(type & CUPS_PRINTER_DELETE)) -+ found_cups_printer (remote_host, uri, info); -+ - recheck_timer (); - - /* Don't remove this I/O source */ -@@ -1326,12 +2301,10 @@ update_netifs (void) - freeifaddrs (ifaddr); - } - --void --broadcast_browse_packets (int type, int state, -- const char *local_uri, const char *location, -- const char *info, const char *make_model, -- const char *browse_options) -+static void -+broadcast_browse_packets (gpointer data, gpointer user_data) - { -+ browse_data_t *bdata = data; - netif_t *browse; - char packet[2048]; - char uri[HTTP_MAX_URI]; -@@ -1345,262 +2318,102 @@ broadcast_browse_packets (int type, int - browse != NULL; - browse = (netif_t *)cupsArrayNext (netifs)) { - /* Replace 'localhost' with our IP address on this interface */ -- httpSeparateURI(HTTP_URI_CODING_ALL, local_uri, -+ httpSeparateURI(HTTP_URI_CODING_ALL, bdata->uri, - scheme, sizeof(scheme), - username, sizeof(username), - host, sizeof(host), - &port, - resource, sizeof(resource)); -- httpAssembleURI(HTTP_URI_CODING_ALL, uri, sizeof (uri), -- scheme, username, browse->address, port, resource); -- -- if (snprintf (packet, sizeof (packet), -- "%x " /* type */ -- "%x " /* state */ -- "%s " /* uri */ -- "\"%s\" " /* location */ -- "\"%s\" " /* info */ -- "\"%s\" " /* make-and-model */ -- "lease-duration=%d" /* BrowseTimeout */ -- "%s%s" /* other browse options */ -- "\n", -- type, state, uri, location, -- info, make_model, -- BrowseTimeout, -- browse_options ? " " : "", -- browse_options ? browse_options : "") >= sizeof (packet)) { -- debug_printf ("cups-browsed: oversize packet not sent\n"); -- continue; -- } -- -- debug_printf("cups-browsed: packet to send:\n%s", packet); -- -- int err = sendto (browsesocket, packet, -- strlen (packet), 0, -- &browse->broadcast.addr, -- httpAddrLength (&browse->broadcast)); -- if (err) -- debug_printf("cupsd-browsed: sendto returned %d: %s\n", -- err, strerror (errno)); -- } --} -- --gboolean --send_browse_data (gpointer data) --{ -- static const char * const rattrs[] = { "printer-type", -- "printer-state", -- "printer-uri-supported", -- "printer-info", -- "printer-location", -- "printer-make-and-model", -- "auth-info-required", -- "printer-uuid", -- "job-template" }; -- ipp_t *request, *response = NULL; -- ipp_attribute_t *attr; -- http_t *conn = NULL; -- -- update_netifs (); -- res_init (); -- conn = httpConnectEncrypt ("localhost", BrowsePort, -- HTTP_ENCRYPT_IF_REQUESTED); -- -- if (conn == NULL) { -- debug_printf("cups-browsed: browse send failed to connect to localhost\n"); -- goto fail; -- } -- -- request = ippNewRequest(CUPS_GET_PRINTERS); -- ippAddStrings (request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, -- "requested-attributes", sizeof (rattrs) / sizeof (rattrs[0]), -- NULL, rattrs); -- ippAddString (request, IPP_TAG_OPERATION, IPP_TAG_NAME, -- "requesting-user-name", NULL, cupsUser ()); -- -- response = cupsDoRequest (conn, request, "/"); -- if (cupsLastError() > IPP_OK_CONFLICT) { -- debug_printf("cups-browsed: browse send failed for localhost: %s\n", -- cupsLastErrorString ()); -- goto fail; -- } -- -- for (attr = ippFirstAttribute(response); attr; -- attr = ippNextAttribute(response)) { -- int type = -1, state = -1; -- const char *uri = NULL; -- gchar *location = NULL; -- gchar *info = NULL; -- gchar *make_model = NULL; -- GString *browse_options = g_string_new (""); -- -- /* Skip any non-printer attributes */ -- while (attr && ippGetGroupTag(attr) != IPP_TAG_PRINTER) -- attr = ippNextAttribute(response); -- -- if (!attr) -- break; -- -- while (attr && ippGetGroupTag(attr) == IPP_TAG_PRINTER) { -- const char *attrname = ippGetName(attr); -- int value_tag = ippGetValueTag(attr); -- -- if (!strcmp(attrname, "printer-type") && -- value_tag == IPP_TAG_ENUM) { -- type = ippGetInteger(attr, 0); -- if (type & CUPS_PRINTER_NOT_SHARED) { -- /* Skip CUPS queues not marked as shared */ -- state = -1; -- type = -1; -- break; -- } -- } else if (!strcmp(attrname, "printer-state") && -- value_tag == IPP_TAG_ENUM) -- state = ippGetInteger(attr, 0); -- else if (!strcmp(attrname, "printer-uri-supported") && -- value_tag == IPP_TAG_URI) -- uri = ippGetString(attr, 0, NULL); -- else if (!strcmp(attrname, "printer-location") && -- value_tag == IPP_TAG_TEXT) { -- /* Remove quotes */ -- gchar **tokens = g_strsplit (ippGetString(attr, 0, NULL), "\"", -1); -- location = g_strjoinv ("", tokens); -- g_strfreev (tokens); -- } else if (!strcmp(attrname, "printer-info") && -- value_tag == IPP_TAG_TEXT) { -- /* Remove quotes */ -- gchar **tokens = g_strsplit (ippGetString(attr, 0, NULL), "\"", -1); -- info = g_strjoinv ("", tokens); -- g_strfreev (tokens); -- } else if (!strcmp(attrname, "printer-make-and-model") && -- value_tag == IPP_TAG_TEXT) { -- /* Remove quotes */ -- gchar **tokens = g_strsplit (ippGetString(attr, 0, NULL), "\"", -1); -- make_model = g_strjoinv ("", tokens); -- g_strfreev (tokens); -- } else if (!strcmp(attrname, "auth-info-required") && -- value_tag == IPP_TAG_KEYWORD) { -- if (strcmp (ippGetString(attr, 0, NULL), "none")) -- g_string_append_printf (browse_options, "auth-info-required=%s ", -- ippGetString(attr, 0, NULL)); -- } else if (!strcmp(attrname, "printer-uuid") && -- value_tag == IPP_TAG_URI) -- g_string_append_printf (browse_options, "uuid=%s ", -- ippGetString(attr, 0, NULL)); -- else if (!strcmp(attrname, "job-sheets-default") && -- value_tag == IPP_TAG_NAME && -- ippGetCount(attr) == 2) -- g_string_append_printf (browse_options, "job-sheets=%s,%s ", -- ippGetString(attr, 0, NULL), -- ippGetString(attr, 1, NULL)); -- else if (strstr(attrname, "-default")) { -- gchar *name = g_strdup (attrname); -- gchar *value = NULL; -- *strstr (name, "-default") = '\0'; -- -- switch (value_tag) { -- gchar **tokens; -- -- case IPP_TAG_KEYWORD: -- case IPP_TAG_STRING: -- case IPP_TAG_NAME: -- /* Escape value */ -- tokens = g_strsplit_set (ippGetString(attr, 0, NULL), -- " \"\'\\", -1); -- value = g_strjoinv ("\\", tokens); -- g_strfreev (tokens); -- break; -- -- default: -- /* other values aren't needed? */ -- debug_printf("cups-browsed: skipping %s (%d)\n", name, value_tag); -- break; -- } -- -- if (value) { -- g_string_append_printf (browse_options, "%s=%s ", name, value); -- g_free (value); -- } -- -- g_free (name); -- } -- -- attr = ippNextAttribute(response); -- } -- -- if (type != -1 && state != -1 && uri && location && info && make_model) { -- gchar *browse_options_str = g_string_free (browse_options, FALSE); -- browse_options = NULL; -- g_strchomp (browse_options_str); -- -- broadcast_browse_packets (type, state, uri, location, -- info, make_model, -- browse_options_str); -- -- g_free (browse_options_str); -- } -- -- if (make_model) -- g_free (make_model); -- -- if (info) -- g_free (info); -+ httpAssembleURI(HTTP_URI_CODING_ALL, uri, sizeof (uri), -+ scheme, username, browse->address, port, resource); - -- if (location) -- g_free (location); -+ if (snprintf (packet, sizeof (packet), -+ "%x " /* type */ -+ "%x " /* state */ -+ "%s " /* uri */ -+ "\"%s\" " /* location */ -+ "\"%s\" " /* info */ -+ "\"%s\" " /* make-and-model */ -+ "lease-duration=%d" /* BrowseTimeout */ -+ "%s%s" /* other browse options */ -+ "\n", -+ bdata->type, -+ bdata->state, -+ uri, -+ bdata->location, -+ bdata->info, -+ bdata->make_model, -+ BrowseTimeout, -+ bdata->browse_options ? " " : "", -+ bdata->browse_options ? bdata->browse_options : "") -+ >= sizeof (packet)) { -+ debug_printf ("cups-browsed: oversize packet not sent\n"); -+ continue; -+ } - -- if (browse_options) -- g_string_free (browse_options, TRUE); -+ debug_printf("cups-browsed: packet to send:\n%s", packet); - -- if (!attr) -- break; -+ int err = sendto (browsesocket, packet, -+ strlen (packet), 0, -+ &browse->broadcast.addr, -+ httpAddrLength (&browse->broadcast)); -+ if (err == -1) -+ debug_printf("cupsd-browsed: sendto returned %d: %s\n", -+ err, strerror (errno)); - } -+} - -- fail: -- if (response) -- ippDelete(response); -- -- if (conn) -- httpClose (conn); -- -+gboolean -+send_browse_data (gpointer data) -+{ -+ update_netifs (); -+ res_init (); -+ update_local_printers (); -+ g_list_foreach (browse_data, broadcast_browse_packets, NULL); - g_timeout_add_seconds (BrowseInterval, send_browse_data, NULL); - - /* Stop this timeout handler, we called a new one */ - return FALSE; - } - --gboolean --browse_poll (gpointer data) -+static browsepoll_printer_t * -+new_browsepoll_printer (const char *uri_supported, -+ const char *info) -+{ -+ browsepoll_printer_t *printer = g_malloc (sizeof (browsepoll_printer_t)); -+ printer->uri_supported = g_strdup (uri_supported); -+ printer->info = g_strdup (info); -+ return printer; -+} -+ -+static void -+browsepoll_printer_free (gpointer data) -+{ -+ browsepoll_printer_t *printer = data; -+ free (printer->uri_supported); -+ free (printer->info); -+ free (printer); -+} -+ -+static void -+browse_poll_get_printers (browsepoll_t *context, http_t *conn) - { -- static const char * const rattrs[] = { "printer-uri-supported" }; -- char *server = strdup (data); -+ static const char * const rattrs[] = { "printer-uri-supported", -+ "printer-info"}; - ipp_t *request, *response = NULL; - ipp_attribute_t *attr; -- http_t *conn; -- int port = BrowsePort; -- char *colon; -- -- debug_printf ("cups-browsed: browse polling %s\n", server); -- -- colon = strchr (server, ':'); -- if (colon) { -- char *endptr; -- unsigned long n; -- *colon++ = '\0'; -- n = strtoul (colon, &endptr, 10); -- if (endptr != colon && n < INT_MAX) -- port = (int) n; -- } -- -- res_init (); -- conn = httpConnectEncrypt (server, port, HTTP_ENCRYPT_IF_REQUESTED); -+ GList *printers = NULL; - -- if (conn == NULL) { -- debug_printf("cups-browsed: browse poll failed to connect to %s\n", server); -- goto fail; -- } -+ debug_printf ("cups-browsed [BrowsePoll %s:%d]: CUPS-Get-Printers\n", -+ context->server, context->port); - - request = ippNewRequest(CUPS_GET_PRINTERS); -+ if (context->major > 0) { -+ debug_printf("cups-browsed [BrowsePoll %s:%d]: setting IPP version %d.%d\n", -+ context->server, context->port, context->major, -+ context->minor); -+ ippSetVersion (request, context->major, context->minor); -+ } - - ippAddStrings (request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, - "requested-attributes", sizeof (rattrs) / sizeof (rattrs[0]), -@@ -1621,13 +2434,14 @@ browse_poll (gpointer data) - - response = cupsDoRequest(conn, request, "/"); - if (cupsLastError() > IPP_OK_CONFLICT) { -- debug_printf("cups-browsed: browse poll failed for server %s: %s\n", -- server, cupsLastErrorString ()); -+ debug_printf("cups-browsed [BrowsePoll %s:%d]: failed: %s\n", -+ context->server, context->port, cupsLastErrorString ()); - goto fail; - } - - for (attr = ippFirstAttribute(response); attr; - attr = ippNextAttribute(response)) { -+ browsepoll_printer_t *printer; - const char *uri, *info; - - while (attr && ippGetGroupTag(attr) != IPP_TAG_PRINTER) -@@ -1639,35 +2453,287 @@ browse_poll (gpointer data) - uri = NULL; - info = NULL; - while (attr && ippGetGroupTag(attr) == IPP_TAG_PRINTER) { -- if (!strcmp (ippGetName(attr), "printer-uri-supported") && -+ -+ if (!strcasecmp (ippGetName(attr), "printer-uri-supported") && - ippGetValueTag(attr) == IPP_TAG_URI) - uri = ippGetString(attr, 0, NULL); -- else if (!strcmp (ippGetName(attr), "printer-info") && -+ else if (!strcasecmp (ippGetName(attr), "printer-info") && - ippGetValueTag(attr) == IPP_TAG_TEXT) - info = ippGetString(attr, 0, NULL); - - attr = ippNextAttribute(response); - } - -- if (uri) -- found_cups_printer (server, uri, info); -+ if (uri) { -+ found_cups_printer (context->server, uri, info); -+ printer = new_browsepoll_printer (uri, info); -+ printers = g_list_insert (printers, printer, 0); -+ } - - if (!attr) - break; - } - -+ g_list_free_full (context->printers, browsepoll_printer_free); -+ context->printers = printers; - recheck_timer (); - - fail: - if (response) - ippDelete(response); -+} -+ -+static void -+browse_poll_create_subscription (browsepoll_t *context, http_t *conn) -+{ -+ static const char * const events[] = { "printer-added", -+ "printer-changed", -+ "printer-config-changed", -+ "printer-modified", -+ "printer-deleted", -+ "printer-state-changed" }; -+ ipp_t *request, *response = NULL; -+ ipp_attribute_t *attr; -+ -+ debug_printf ("cups-browsed [BrowsePoll %s:%d]: IPP-Create-Subscription\n", -+ context->server, context->port); -+ -+ request = ippNewRequest(IPP_CREATE_PRINTER_SUBSCRIPTION); -+ if (context->major > 0) { -+ debug_printf("cups-browsed [BrowsePoll %s:%d]: setting IPP version %d.%d\n", -+ context->server, context->port, context->major, -+ context->minor); -+ ippSetVersion (request, context->major, context->minor); -+ } -+ -+ ippAddString (request, IPP_TAG_OPERATION, IPP_TAG_URI, -+ "printer-uri", NULL, "/"); -+ ippAddString (request, IPP_TAG_SUBSCRIPTION, IPP_TAG_KEYWORD, -+ "notify-pull-method", NULL, "ippget"); -+ ippAddString (request, IPP_TAG_SUBSCRIPTION, IPP_TAG_CHARSET, -+ "notify-charset", NULL, "utf-8"); -+ ippAddString (request, IPP_TAG_SUBSCRIPTION, IPP_TAG_NAME, -+ "requesting-user-name", NULL, cupsUser ()); -+ ippAddStrings (request, IPP_TAG_SUBSCRIPTION, IPP_TAG_KEYWORD, -+ "notify-events", sizeof (events) / sizeof (events[0]), -+ NULL, events); -+ ippAddInteger (request, IPP_TAG_SUBSCRIPTION, IPP_TAG_INTEGER, -+ "notify-time-interval", BrowseInterval); -+ -+ response = cupsDoRequest (conn, request, "/"); -+ if (!response || ippGetStatusCode (response) > IPP_OK_CONFLICT) { -+ debug_printf("cupsd-browsed [BrowsePoll %s:%d]: failed: %s\n", -+ context->server, context->port, cupsLastErrorString ()); -+ context->subscription_id = -1; -+ context->can_subscribe = FALSE; -+ goto fail; -+ } -+ -+ for (attr = ippFirstAttribute(response); attr; -+ attr = ippNextAttribute(response)) { -+ if (ippGetGroupTag (attr) == IPP_TAG_SUBSCRIPTION) { -+ if (ippGetValueTag (attr) == IPP_TAG_INTEGER && -+ !strcasecmp (ippGetName (attr), "notify-subscription-id")) { -+ context->subscription_id = ippGetInteger (attr, 0); -+ debug_printf("cups-browsed [BrowsePoll %s:%d]: subscription ID=%d\n", -+ context->server, context->port, context->subscription_id); -+ break; -+ } -+ } -+ } -+ -+ if (!attr) { -+ debug_printf("cups-browsed [BrowsePoll %s:%d]: no ID returned\n", -+ context->server, context->port); -+ context->subscription_id = -1; -+ context->can_subscribe = FALSE; -+ } -+ -+fail: -+ if (response) -+ ippDelete(response); -+} -+ -+static void -+browse_poll_cancel_subscription (browsepoll_t *context) -+{ -+ ipp_t *request, *response = NULL; -+ http_t *conn = httpConnectEncrypt (context->server, context->port, -+ HTTP_ENCRYPT_IF_REQUESTED); -+ -+ if (conn == NULL) { -+ debug_printf("cups-browsed [BrowsePoll %s:%d]: connection failure " -+ "attempting to cancel\n", context->server, context->port); -+ return; -+ } -+ -+ debug_printf ("cups-browsed [BrowsePoll %s:%d]: IPP-Cancel-Subscription\n", -+ context->server, context->port); -+ -+ request = ippNewRequest(IPP_CANCEL_SUBSCRIPTION); -+ if (context->major > 0) { -+ debug_printf("cups-browsed [BrowsePoll %s:%d]: setting IPP version %d.%d\n", -+ context->server, context->port, context->major, -+ context->minor); -+ ippSetVersion (request, context->major, context->minor); -+ } -+ -+ ippAddString (request, IPP_TAG_OPERATION, IPP_TAG_URI, -+ "printer-uri", NULL, "/"); -+ ippAddString (request, IPP_TAG_OPERATION, IPP_TAG_NAME, -+ "requesting-user-name", NULL, cupsUser ()); -+ ippAddInteger (request, IPP_TAG_OPERATION, IPP_TAG_INTEGER, -+ "notify-subscription-id", context->subscription_id); -+ -+ response = cupsDoRequest (conn, request, "/"); -+ if (!response || ippGetStatusCode (response) > IPP_OK_CONFLICT) -+ debug_printf("cupsd-browsed [BrowsePoll %s:%d]: failed: %s\n", -+ context->server, context->port, cupsLastErrorString ()); -+ -+ if (response) -+ ippDelete(response); -+ -+ httpClose (conn); -+} -+ -+static gboolean -+browse_poll_get_notifications (browsepoll_t *context, http_t *conn) -+{ -+ ipp_t *request, *response = NULL; -+ ipp_status_t status; -+ gboolean get_printers = FALSE; -+ -+ debug_printf ("cups-browsed [BrowsePoll %s:%d]: IPP-Get-Notifications\n", -+ context->server, context->port); -+ -+ request = ippNewRequest(IPP_GET_NOTIFICATIONS); -+ if (context->major > 0) { -+ debug_printf("cups-browsed [BrowsePoll %s:%d]: setting IPP version %d.%d\n", -+ context->server, context->port, context->major, -+ context->minor); -+ ippSetVersion (request, context->major, context->minor); -+ } -+ -+ ippAddString (request, IPP_TAG_OPERATION, IPP_TAG_URI, -+ "printer-uri", NULL, "/"); -+ ippAddString (request, IPP_TAG_OPERATION, IPP_TAG_NAME, -+ "requesting-user-name", NULL, cupsUser ()); -+ ippAddInteger (request, IPP_TAG_OPERATION, IPP_TAG_INTEGER, -+ "notify-subscription-ids", context->subscription_id); -+ ippAddInteger (request, IPP_TAG_OPERATION, IPP_TAG_INTEGER, -+ "notify-sequence-numbers", context->sequence_number + 1); -+ -+ response = cupsDoRequest (conn, request, "/"); -+ if (!response) -+ status = cupsLastError (); -+ else -+ status = ippGetStatusCode (response); -+ -+ if (status == IPP_NOT_FOUND) { -+ /* Subscription lease has expired. */ -+ debug_printf ("cups-browsed [BrowsePoll %s:%d]: Lease expired\n", -+ context->server, context->port); -+ browse_poll_create_subscription (context, conn); -+ get_printers = TRUE; -+ } else if (status > IPP_OK_CONFLICT) { -+ debug_printf("cupsd-browsed [BrowsePoll %s:%d]: failed: %s\n", -+ context->server, context->port, cupsLastErrorString ()); -+ context->can_subscribe = FALSE; -+ browse_poll_cancel_subscription (context); -+ context->subscription_id = -1; -+ context->sequence_number = 0; -+ get_printers = TRUE; -+ } -+ -+ if (!get_printers) { -+ ipp_attribute_t *attr; -+ gboolean seen_event = FALSE; -+ int last_seq = context->sequence_number; -+ assert (response != NULL); -+ for (attr = ippFirstAttribute(response); attr; -+ attr = ippNextAttribute(response)) -+ if (ippGetGroupTag (attr) == IPP_TAG_EVENT_NOTIFICATION) { -+ /* There is a printer-* event here. */ -+ seen_event = TRUE; -+ -+ if (!strcmp (ippGetName (attr), "notify-sequence-number") && -+ ippGetValueTag (attr) == IPP_TAG_INTEGER) -+ last_seq = ippGetInteger (attr, 0); -+ } -+ -+ if (seen_event) { -+ debug_printf("cups-browsed [BrowsePoll %s:%d]: printer-* event\n", -+ context->server, context->port); -+ context->sequence_number = last_seq; -+ get_printers = TRUE; -+ } else -+ debug_printf("cups-browsed [BrowsePoll %s:%d]: no events\n", -+ context->server, context->port); -+ } -+ -+ if (response) -+ ippDelete (response); -+ -+ return get_printers; -+} -+ -+static void -+browsepoll_printer_keepalive (gpointer data, gpointer user_data) -+{ -+ browsepoll_printer_t *printer = data; -+ const char *server = user_data; -+ found_cups_printer (server, printer->uri_supported, printer->info); -+} -+ -+gboolean -+browse_poll (gpointer data) -+{ -+ browsepoll_t *context = data; -+ http_t *conn = NULL; -+ gboolean get_printers = FALSE; -+ -+ debug_printf ("cups-browsed: browse polling %s:%d\n", -+ context->server, context->port); -+ -+ res_init (); -+ -+ conn = httpConnectEncrypt (context->server, context->port, -+ HTTP_ENCRYPT_IF_REQUESTED); -+ if (conn == NULL) { -+ debug_printf("cups-browsed [BrowsePoll %s:%d]: failed to connect\n", -+ context->server, context->port); -+ goto fail; -+ } -+ -+ if (context->can_subscribe) { -+ if (context->subscription_id == -1) { -+ /* The first time this callback is run we need to create the IPP -+ * subscription to watch to printer-* events. */ -+ browse_poll_create_subscription (context, conn); -+ get_printers = TRUE; -+ } else -+ /* On subsequent runs, check for notifications using our -+ * subscription. */ -+ get_printers = browse_poll_get_notifications (context, conn); -+ } -+ else -+ get_printers = TRUE; -+ -+ update_local_printers (); -+ inhibit_local_printers_update = TRUE; -+ if (get_printers) -+ browse_poll_get_printers (context, conn); -+ else -+ g_list_foreach (context->printers, browsepoll_printer_keepalive, -+ context->server); -+ -+ inhibit_local_printers_update = FALSE; -+ -+fail: - - if (conn) - httpClose (conn); - -- if (server) -- free (server); -- - /* Call a new timeout handler so that we run again */ - g_timeout_add_seconds (BrowseInterval, browse_poll, data); - -@@ -1686,7 +2752,7 @@ compare_pointers (void *a, void *b, void - } - - int compare_remote_printers (remote_printer_t *a, remote_printer_t *b) { -- return strcmp(a->name, b->name); -+ return strcasecmp(a->name, b->name); - } - - static void -@@ -1698,12 +2764,53 @@ sigterm_handler(int sig) { - debug_printf("cups-browsed: Caught signal %d, shutting down ...\n", sig); - } - -+static void -+sigusr1_handler(int sig) { -+ (void)sig; /* remove compiler warnings... */ -+ -+ /* Turn off auto shutdown mode... */ -+ autoshutdown = 0; -+ debug_printf("cups-browsed: Caught signal %d, switching to permanent mode ...\n", sig); -+ /* If there is still an active auto shutdown timer, kill it */ -+ if (autoshutdown_exec_id > 0) { -+ debug_printf ("cups-browsed: We have left auto shutdown mode, killing auto shutdown timer.\n"); -+ g_source_destroy(g_main_context_find_source_by_id(NULL, -+ autoshutdown_exec_id)); -+ autoshutdown_exec_id = 0; -+ } -+} -+ -+static void -+sigusr2_handler(int sig) { -+ (void)sig; /* remove compiler warnings... */ -+ -+ /* Turn on auto shutdown mode... */ -+ autoshutdown = 1; -+ debug_printf("cups-browsed: Caught signal %d, switching to auto shutdown mode ...\n", sig); -+ /* If there are no printers schedule the shutdown in autoshutdown_timeout -+ seconds */ -+ if (!autoshutdown_exec_id && -+ cupsArrayCount(remote_printers) == 0) { -+ debug_printf ("cups-browsed: We entered auto shutdown mode and no printers are there to make available, shutting down in %d sec...\n", autoshutdown_timeout); -+ autoshutdown_exec_id = -+ g_timeout_add_seconds (autoshutdown_timeout, autoshutdown_execute, -+ NULL); -+ } -+} -+ - static int - read_browseallow_value (const char *value) - { - char *p; - struct in_addr addr; -- allow_t *allow = calloc (1, sizeof (allow_t)); -+ allow_t *allow; -+ -+ if (value && !strcasecmp (value, "all")) { -+ browseallow_all = TRUE; -+ return 0; -+ } -+ -+ allow = calloc (1, sizeof (allow_t)); - if (value == NULL) - goto fail; - p = strchr (value, '/'); -@@ -1785,7 +2892,7 @@ read_configuration (const char *filename - else if (!strcasecmp(p, "cups")) - protocols |= BROWSE_CUPS; - else if (strcasecmp(p, "none")) -- debug_printf("cups-browsed: unknown protocol '%s'\n", p); -+ debug_printf("cups-browsed: Unknown protocol '%s'\n", p); - - p = strtok_r (NULL, delim, &saveptr); - } -@@ -1797,44 +2904,153 @@ read_configuration (const char *filename - else - BrowseLocalProtocols = BrowseRemoteProtocols = protocols; - } else if (!strcasecmp(line, "BrowsePoll") && value) { -- char **old = BrowsePoll; -- BrowsePoll = realloc (BrowsePoll, (NumBrowsePoll + 1) * sizeof (char *)); -+ browsepoll_t **old = BrowsePoll; -+ BrowsePoll = realloc (BrowsePoll, -+ (NumBrowsePoll + 1) * -+ sizeof (browsepoll_t *)); - if (!BrowsePoll) { - debug_printf("cups-browsed: unable to realloc: ignoring BrowsePoll line\n"); - BrowsePoll = old; - } else { -+ char *colon, *slash; -+ browsepoll_t *b = g_malloc0 (sizeof (browsepoll_t)); - debug_printf("cups-browsed: Adding BrowsePoll server: %s\n", value); -- BrowsePoll[NumBrowsePoll++] = strdup (value); -+ b->server = strdup (value); -+ b->port = BrowsePort; -+ b->can_subscribe = TRUE; /* first assume subscriptions work */ -+ b->subscription_id = -1; -+ slash = strchr (b->server, '/'); -+ if (slash) { -+ *slash++ = '\0'; -+ if (!strcasecmp (slash, "version=1.0")) { -+ b->major = 1; -+ b->minor = 0; -+ } else if (!strcasecmp (slash, "version=1.1")) { -+ b->major = 1; -+ b->minor = 1; -+ } else if (!strcasecmp (slash, "version=2.0")) { -+ b->major = 2; -+ b->minor = 0; -+ } else if (!strcasecmp (slash, "version=2.1")) { -+ b->major = 2; -+ b->minor = 1; -+ } else if (!strcasecmp (slash, "version=2.2")) { -+ b->major = 2; -+ b->minor = 2; -+ } else { -+ debug_printf ("ignoring unknown server option: %s\n", slash); -+ } -+ } else -+ b->major = 0; -+ -+ colon = strchr (b->server, ':'); -+ if (colon) { -+ char *endptr; -+ unsigned long n; -+ *colon++ = '\0'; -+ n = strtoul (colon, &endptr, 10); -+ if (endptr != colon && n < INT_MAX) -+ b->port = (int) n; -+ } -+ -+ BrowsePoll[NumBrowsePoll++] = b; - } -- } else if (!strcasecmp(line, "BrowseAllow")) -+ } else if (!strcasecmp(line, "BrowseAllow")) { - if (read_browseallow_value (value)) - debug_printf ("cups-browsed: BrowseAllow value \"%s\" not understood\n", - value); -+ } else if (!strcasecmp(line, "DomainSocket") && value) { -+ if (value[0] != '\0') -+ DomainSocket = strdup(value); -+ } else if (!strcasecmp(line, "CreateIPPPrinterQueues") && value) { -+ if (!strcasecmp(value, "yes") || !strcasecmp(value, "true") || -+ !strcasecmp(value, "on") || !strcasecmp(value, "1")) -+ CreateIPPPrinterQueues = 1; -+ else if (!strcasecmp(value, "no") || !strcasecmp(value, "false") || -+ !strcasecmp(value, "off") || !strcasecmp(value, "0")) -+ CreateIPPPrinterQueues = 0; -+ } else if (!strcasecmp(line, "AutoShutdown") && value) { -+ char *p, *saveptr; -+ p = strtok_r (value, delim, &saveptr); -+ while (p) { -+ if (!strcasecmp(p, "On") || !strcasecmp(p, "Yes") || -+ !strcasecmp(p, "True") || !strcasecmp(p, "1")) { -+ autoshutdown = 1; -+ debug_printf("cups-browsed: Turning on auto shutdown mode.\n"); -+ } else if (!strcasecmp(p, "Off") || !strcasecmp(p, "No") || -+ !strcasecmp(p, "False") || !strcasecmp(p, "0")) { -+ autoshutdown = 0; -+ debug_printf("cups-browsed: Turning off auto shutdown mode (permanent mode).\n"); -+ } else if (!strcasecmp(p, "avahi")) { -+ autoshutdown_avahi = 1; -+ debug_printf("cups-browsed: Turning on auto shutdown control by appearing and disappearing of the Avahi server.\n"); -+ } else if (strcasecmp(p, "none")) -+ debug_printf("cups-browsed: Unknown mode '%s'\n", p); -+ p = strtok_r (NULL, delim, &saveptr); -+ } -+ } else if (!strcasecmp(line, "AutoShutdownTimeout") && value) { -+ int t = atoi(value); -+ if (t >= 0) { -+ autoshutdown_timeout = t; -+ debug_printf("cups-browsed: Set auto shutdown timeout to %d sec.\n", -+ t); -+ } else -+ debug_printf("cups-browsed: Invalid auto shutdown timeout value: %d\n", -+ t); -+ } - } - - cupsFileClose(fp); - } - -+static void -+find_previous_queue (gpointer key, -+ gpointer value, -+ gpointer user_data) -+{ -+ const char *name = key; -+ const local_printer_t *printer = value; -+ remote_printer_t *p; -+ if (printer->cups_browsed_controlled) { -+ /* Queue found, add to our list */ -+ p = create_local_queue (name, -+ printer->device_uri, -+ "", "", "", "", NULL, NULL, 1); -+ if (p) { -+ /* Mark as unconfirmed, if no Avahi report of this queue appears -+ in a certain time frame, we will remove the queue */ -+ p->status = STATUS_UNCONFIRMED; -+ -+ if (BrowseRemoteProtocols & BROWSE_CUPS) -+ p->timeout = time(NULL) + BrowseTimeout; -+ else -+ p->timeout = time(NULL) + TIMEOUT_CONFIRM; -+ -+ p->duplicate = 0; -+ debug_printf("cups-browsed: Found CUPS queue %s (URI: %s) from previous session.\n", -+ p->name, p->uri); -+ } else { -+ debug_printf("cups-browsed: ERROR: Unable to allocate memory.\n"); -+ exit(1); -+ } -+ } -+} -+ - int main(int argc, char*argv[]) { --#ifdef HAVE_AVAHI -- AvahiClient *client = NULL; -- AvahiServiceBrowser *sb1 = NULL, *sb2 = NULL; -- int error; --#endif /* HAVE_AVAHI */ - int ret = 1; - http_t *http; -- cups_dest_t *dests, -- *dest; -- int i, -- num_dests; -+ int i; - const char *val; - remote_printer_t *p; - - /* Turn on debug mode if requested */ -- if (argc >= 2 && -- (!strcmp(argv[1], "--debug") || !strcmp(argv[1], "-d") || -- !strncmp(argv[1], "-v", 2))) -- debug = 1; -+ if (argc >= 2) -+ for (i = 1; i < argc; i++) -+ if (!strcasecmp(argv[i], "--debug") || !strcasecmp(argv[i], "-d") || -+ !strncasecmp(argv[i], "-v", 2)) { -+ debug = 1; -+ debug_printf("cups-browsed: Reading command line: %s\n", argv[i]); -+ } - - /* Initialise the browseallow array */ - browseallow = cupsArrayNew(compare_pointers, NULL); -@@ -1842,6 +3058,79 @@ int main(int argc, char*argv[]) { - /* Read in cups-browsed.conf */ - read_configuration (NULL); - -+ /* Parse command line options after reading the config file to override -+ config file settings */ -+ if (argc >= 2) { -+ for (i = 1; i < argc; i++) -+ if (!strncasecmp(argv[i], "--autoshutdown-timeout", 22)) { -+ debug_printf("cups-browsed: Reading command line: %s\n", argv[i]); -+ if (argv[i][22] == '=' && argv[i][23]) -+ val = argv[i] + 23; -+ else if (!argv[i][22] && i < argc -1) { -+ i++; -+ debug_printf("cups-browsed: Reading command line: %s\n", argv[i]); -+ val = argv[i]; -+ } else { -+ fprintf(stderr, "cups-browsed: Expected auto shutdown timeout setting after \"--autoshutdown-timeout\" option.\n"); -+ exit(1); -+ } -+ int t = atoi(val); -+ if (t >= 0) { -+ autoshutdown_timeout = t; -+ debug_printf("cups-browsed: Set auto shutdown timeout to %d sec.\n", -+ t); -+ } else { -+ debug_printf("cups-browsed: Invalid auto shutdown timeout value: %d\n", -+ t); -+ exit(1); -+ } -+ } else if (!strncasecmp(argv[i], "--autoshutdown", 14)) { -+ debug_printf("cups-browsed: Reading command line: %s\n", argv[i]); -+ if (argv[i][14] == '=' && argv[i][15]) -+ val = argv[i] + 15; -+ else if (!argv[i][14] && i < argc -1) { -+ i++; -+ debug_printf("cups-browsed: Reading command line: %s\n", argv[i]); -+ val = argv[i]; -+ } else { -+ fprintf(stderr, "cups-browsed: Expected auto shutdown setting after \"--autoshutdown\" option.\n"); -+ exit(1); -+ } -+ if (!strcasecmp(val, "On") || !strcasecmp(val, "Yes") || -+ !strcasecmp(val, "True") || !strcasecmp(val, "1")) { -+ autoshutdown = 1; -+ debug_printf("cups-browsed: Turning on auto shutdown mode.\n"); -+ } else if (!strcasecmp(val, "Off") || !strcasecmp(val, "No") || -+ !strcasecmp(val, "False") || !strcasecmp(val, "0")) { -+ autoshutdown = 0; -+ debug_printf("cups-browsed: Turning off auto shutdown mode (permanent mode).\n"); -+ } else if (!strcasecmp(val, "avahi")) { -+ autoshutdown_avahi = 1; -+ debug_printf("cups-browsed: Turning on auto shutdown control by appearing and disappearing of the Avahi server.\n"); -+ } else if (strcasecmp(val, "none")) { -+ debug_printf("cups-browsed: Unknown mode '%s'\n", val); -+ exit(1); -+ } -+ } -+ } -+ -+ /* Set the CUPS_SERVER environment variable to assure that cups-browsed -+ always works with the local CUPS daemon and never with a remote one -+ specified by a client.conf file */ -+#ifdef CUPS_DEFAULT_DOMAINSOCKET -+ if (DomainSocket == NULL) -+ DomainSocket = CUPS_DEFAULT_DOMAINSOCKET; -+#endif -+ if (DomainSocket != NULL) { -+ struct stat sockinfo; /* Domain socket information */ -+ if (!stat(DomainSocket, &sockinfo) && -+ (sockinfo.st_mode & S_IRWXO) == S_IRWXO) -+ setenv("CUPS_SERVER", DomainSocket, 1); -+ else -+ setenv("CUPS_SERVER", "localhost", 1); -+ } else -+ setenv("CUPS_SERVER", "localhost", 1); -+ - if (BrowseLocalProtocols & BROWSE_DNSSD) { - fprintf(stderr, "Local support for DNSSD not implemented\n"); - BrowseLocalProtocols &= ~BROWSE_DNSSD; -@@ -1855,60 +3144,34 @@ int main(int argc, char*argv[]) { - #endif /* HAVE_AVAHI */ - - /* Wait for CUPS daemon to start */ -- while ((http = httpConnectEncrypt(cupsServer(), ippPort(), -- cupsEncryption())) == NULL) -+ while ((http = http_connect_local ()) == NULL) - sleep(1); - - /* Initialise the array of network interfaces */ - netifs = cupsArrayNew(compare_pointers, NULL); - update_netifs (); - -+ local_printers = g_hash_table_new_full (g_str_hash, -+ g_str_equal, -+ g_free, -+ free_local_printer); -+ - /* Read out the currently defined CUPS queues and find the ones which we - have added in an earlier session */ -- num_dests = cupsGetDests(&dests); -+ update_local_printers (); - remote_printers = cupsArrayNew((cups_array_func_t)compare_remote_printers, - NULL); -- if (num_dests > 0) { -- for (i = num_dests, dest = dests; i > 0; i --, dest ++) { -- if ((val = cupsGetOption(CUPS_BROWSED_MARK, dest->num_options, -- dest->options)) != NULL) { -- if (strcasecmp(val, "no") != 0 && strcasecmp(val, "off") != 0 && -- strcasecmp(val, "false") != 0) { -- /* Queue found, add to our list */ -- p = create_local_queue (dest->name, -- strdup(cupsGetOption("device-uri", -- dest->num_options, -- dest->options)), -- "", "", "", ""); -- if (p) { -- /* Mark as unconfirmed, if no Avahi report of this queue appears -- in a certain time frame, we will remove the queue */ -- p->status = STATUS_UNCONFIRMED; -- -- if (BrowseRemoteProtocols & BROWSE_CUPS) -- p->timeout = time(NULL) + BrowseTimeout; -- else -- p->timeout = time(NULL) + TIMEOUT_CONFIRM; -- -- p->duplicate = 0; -- debug_printf("cups-browsed: Found CUPS queue %s (URI: %s) from previous session.\n", -- p->name, p->uri); -- } else { -- debug_printf("cups-browsed: ERROR: Unable to allocate memory.\n"); -- exit(1); -- } -- } -- } -- } -- cupsFreeDests(num_dests, dests); -- } -- httpClose(http); -+ g_hash_table_foreach (local_printers, find_previous_queue, NULL); - - /* Redirect SIGINT and SIGTERM so that we do a proper shutdown, removing -- the CUPS queues which we have created */ -+ the CUPS queues which we have created -+ Use SIGUSR1 and SIGUSR2 to turn off and turn on auto shutdown mode -+ resp. */ - #ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */ - sigset(SIGTERM, sigterm_handler); - sigset(SIGINT, sigterm_handler); -+ sigset(SIGUSR1, sigusr1_handler); -+ sigset(SIGUSR2, sigusr2_handler); - debug_printf("cups-browsed: Using signal handler SIGSET\n"); - #elif defined(HAVE_SIGACTION) - struct sigaction action; /* Actions for POSIX signals */ -@@ -1921,65 +3184,27 @@ int main(int argc, char*argv[]) { - sigaddset(&action.sa_mask, SIGINT); - action.sa_handler = sigterm_handler; - sigaction(SIGINT, &action, NULL); -+ sigemptyset(&action.sa_mask); -+ sigaddset(&action.sa_mask, SIGUSR1); -+ action.sa_handler = sigusr1_handler; -+ sigaction(SIGUSR1, &action, NULL); -+ sigemptyset(&action.sa_mask); -+ sigaddset(&action.sa_mask, SIGUSR2); -+ action.sa_handler = sigusr2_handler; -+ sigaction(SIGUSR2, &action, NULL); - debug_printf("cups-browsed: Using signal handler SIGACTION\n"); - #else - signal(SIGTERM, sigterm_handler); - signal(SIGINT, sigterm_handler); -+ signal(SIGUSR1, sigusr1_handler); -+ signal(SIGUSR2, sigusr2_handler); - debug_printf("cups-browsed: Using signal handler SIGNAL\n"); - #endif /* HAVE_SIGSET */ - - #ifdef HAVE_AVAHI -- if (BrowseRemoteProtocols & BROWSE_DNSSD) { -- /* Allocate main loop object */ -- if (!(glib_poll = avahi_glib_poll_new(NULL, G_PRIORITY_DEFAULT))) { -- debug_printf("cups-browsed: ERROR: Failed to create glib poll object.\n"); -- goto avahi_fail; -- } -- -- /* Allocate a new client */ -- client = avahi_client_new(avahi_glib_poll_get(glib_poll), 0, -- client_callback, NULL, &error); -- -- /* Check wether creating the client object succeeded */ -- if (!client) { -- debug_printf("cups-browsed: ERROR: Failed to create client: %s\n", -- avahi_strerror(error)); -- goto avahi_fail; -- } -- -- /* Create the service browsers */ -- if (!(sb1 = -- avahi_service_browser_new(client, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, -- "_ipp._tcp", NULL, 0, browse_callback, -- client))) { -- debug_printf("cups-browsed: ERROR: Failed to create service browser for IPP: %s\n", -- avahi_strerror(avahi_client_errno(client))); -- goto avahi_fail; -- } -- if (!(sb2 = -- avahi_service_browser_new(client, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, -- "_ipps._tcp", NULL, 0, browse_callback, -- client))) { -- debug_printf("cups-browsed: ERROR: Failed to create service browser for IPPS: %s\n", -- avahi_strerror(avahi_client_errno(client))); -- avahi_fail: -- BrowseRemoteProtocols &= ~BROWSE_DNSSD; -- if (sb2) { -- avahi_service_browser_free(sb2); -- sb2 = NULL; -- } -- -- if (client) { -- avahi_client_free(client); -- client = NULL; -- } -- -- if (glib_poll) { -- avahi_glib_poll_free(glib_poll); -- glib_poll = NULL; -- } -- } -- } -+ if (autoshutdown_avahi) -+ autoshutdown = 1; -+ avahi_init(); - #endif /* HAVE_AVAHI */ - - if (BrowseLocalProtocols & BROWSE_CUPS || -@@ -2025,6 +3250,10 @@ int main(int argc, char*argv[]) { - goto fail; - } - -+ /* Override the default password callback so we don't end up -+ * prompting for it. */ -+ cupsSetPasswordCB2 (password_callback, NULL); -+ - /* Run the main loop */ - gmainloop = g_main_loop_new (NULL, FALSE); - recheck_timer (); -@@ -2047,11 +3276,20 @@ int main(int argc, char*argv[]) { - index < NumBrowsePoll; - index++) { - debug_printf ("cups-browsed: will browse poll %s every %ds\n", -- BrowsePoll[index], BrowseInterval); -+ BrowsePoll[index]->server, BrowseInterval); - g_idle_add (browse_poll, BrowsePoll[index]); - } - } - -+ /* 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 && -+ cupsArrayCount(remote_printers) == 0) { -+ debug_printf ("cups-browsed: No printers found to make available, shutting down in %d sec...\n", autoshutdown_timeout); -+ autoshutdown_exec_id = -+ g_timeout_add_seconds (autoshutdown_timeout, autoshutdown_execute, NULL); -+ } -+ - g_main_loop_run (gmainloop); - - debug_printf("cups-browsed: main loop exited\n"); -@@ -2071,22 +3309,44 @@ fail: - } - handle_cups_queues(NULL); - --#ifdef HAVE_AVAHI -- /* Free the data structures for Bonjour browsing */ -- if (sb1) -- avahi_service_browser_free(sb1); -- if (sb2) -- avahi_service_browser_free(sb2); -+ if (BrowsePoll) { -+ size_t index; -+ for (index = 0; -+ index < NumBrowsePoll; -+ index++) { -+ if (BrowsePoll[index]->can_subscribe && -+ BrowsePoll[index]->subscription_id != -1) -+ browse_poll_cancel_subscription (BrowsePoll[index]); - -- if (client) -- avahi_client_free(client); -+ free (BrowsePoll[index]->server); -+ g_list_free_full (BrowsePoll[index]->printers, -+ browsepoll_printer_free); -+ free (BrowsePoll[index]); -+ } - -- if (glib_poll) -- avahi_glib_poll_free(glib_poll); -+ free (BrowsePoll); -+ } -+ -+ if (local_printers_context) { -+ browse_poll_cancel_subscription (local_printers_context); -+ g_list_free_full (local_printers_context->printers, -+ browsepoll_printer_free); -+ free (local_printers_context); -+ } -+ -+ http_close_local (); -+ -+#ifdef HAVE_AVAHI -+ avahi_shutdown(); - #endif /* HAVE_AVAHI */ - - if (browsesocket != -1) - close (browsesocket); - -+ g_hash_table_destroy (local_printers); -+ -+ if (BrowseLocalProtocols & BROWSE_CUPS) -+ g_list_free_full (browse_data, browse_data_free); -+ - return ret; - } diff --git a/SOURCES/cups-filters-browsed-underscore.patch b/SOURCES/cups-filters-browsed-underscore.patch deleted file mode 100644 index 4c96565..0000000 --- a/SOURCES/cups-filters-browsed-underscore.patch +++ /dev/null @@ -1,34 +0,0 @@ -diff -up cups-filters-1.0.35/NEWS.browsed-underscore cups-filters-1.0.35/NEWS -diff -up cups-filters-1.0.35/utils/cups-browsed.c.browsed-underscore cups-filters-1.0.35/utils/cups-browsed.c ---- cups-filters-1.0.35/utils/cups-browsed.c.browsed-underscore 2015-06-22 15:28:06.219524890 +0100 -+++ cups-filters-1.0.35/utils/cups-browsed.c 2015-06-22 15:36:17.811452072 +0100 -@@ -303,11 +303,11 @@ create_local_queue (const char *name, - * Remove all illegal characters and replace each group of such characters - * by a single dash, return a free()-able string. - * -- * mode = 0: Only allow letters, numbers, and dashes, for turning make/model -- * info into a valid print queue name or into a string which can -- * be supplied as option value in a filter command line without -- * need of quoting -- * mode = 1: Allow also '/', '.', ',', '_', for cleaning up MIME type -+ * mode = 0: Only allow letters, numbers, dashes, and underscores for -+ * turning make/model info into a valid print queue name or -+ * into a string which can be supplied as option value in a -+ * filter command line without need of quoting -+ * mode = 1: Allow also '/', '.', ',' for cleaning up MIME type - * strings (here available Page Description Languages, PDLs) to - * supply them on a filter command line without quoting - * -@@ -339,9 +339,10 @@ remove_bad_chars(const char *str_orig, / - if (((str[i] >= 'A') && (str[i] <= 'Z')) || - ((str[i] >= 'a') && (str[i] <= 'z')) || - ((str[i] >= '0') && (str[i] <= '9')) || -- (mode == 1 && (str[i] == '/' || str[i] == '_' || -+ str[i] == '_' || -+ (mode == 1 && (str[i] == '/' || - str[i] == '.' || str[i] == ','))) { -- /* Letter or number, keep it */ -+ /* Allowed character, keep it */ - havedash = 0; - } else { - /* Replace all other characters by a single '-' */ diff --git a/SOURCES/cups-filters-lookup.patch b/SOURCES/cups-filters-lookup.patch deleted file mode 100644 index 95ed1bd..0000000 --- a/SOURCES/cups-filters-lookup.patch +++ /dev/null @@ -1,27 +0,0 @@ -diff -up cups-filters-1.0.34/utils/cups-browsed.c.lookup cups-filters-1.0.34/utils/cups-browsed.c ---- cups-filters-1.0.34/utils/cups-browsed.c.lookup 2013-06-26 16:23:38.000000000 +0200 -+++ cups-filters-1.0.34/utils/cups-browsed.c 2013-06-26 16:24:28.491804795 +0200 -@@ -990,23 +990,6 @@ found_cups_printer (const char *remote_h - debug_printf("cups-browsed: browsed queue name is %s\n", - local_resource + 9); - -- /* Does the host need resolving? */ -- if (host[strspn (host, "0123456789.")] == '\0') { -- /* Yes. Resolve it. */ -- struct addrinfo hints, *addr; -- memset(&hints, 0, sizeof(struct addrinfo)); -- hints.ai_family = AF_UNSPEC; -- hints.ai_socktype = SOCK_DGRAM; -- hints.ai_flags = 0; -- hints.ai_protocol = 0; -- if (!getaddrinfo (host, NULL, &hints, &addr)) { -- getnameinfo (addr->ai_addr, addr->ai_addrlen, -- host, sizeof(host), -- NULL, 0, 0); -- freeaddrinfo (addr); -- } -- } -- - generate_local_queue(host, port, local_resource, info ? info : "", "", ""); - } - diff --git a/SOURCES/cups-filters-man.patch b/SOURCES/cups-filters-man.patch deleted file mode 100644 index efc5011..0000000 --- a/SOURCES/cups-filters-man.patch +++ /dev/null @@ -1,179 +0,0 @@ -diff -up cups-filters-1.0.35/Makefile.am.man cups-filters-1.0.35/Makefile.am ---- cups-filters-1.0.35/Makefile.am.man 2013-05-15 20:46:22.000000000 +0200 -+++ cups-filters-1.0.35/Makefile.am 2013-07-01 14:03:58.395572035 +0200 -@@ -618,7 +618,6 @@ EXTRA_DIST += \ - # UTILS - # ===== - --EXTRA_DIST += utils/cups-browsed.in - sbin_PROGRAMS = \ - cups-browsed - cups_browsed_SOURCES = \ -@@ -636,6 +635,11 @@ cups_browsed_LDADD = \ - $(GLIB_LIBS) - initrcdir = $(INITDDIR) - initrc_SCRIPTS = utils/cups-browsed -+man_MANS = \ -+ utils/cups-browsed.8 \ -+ utils/cups-browsed.conf.5 -+EXTRA_DIST += utils/cups-browsed.in \ -+ $(man_MANS) - - # === - # PPD -diff -up cups-filters-1.0.35/utils/cups-browsed.8.man cups-filters-1.0.35/utils/cups-browsed.8 ---- cups-filters-1.0.35/utils/cups-browsed.8.man 2013-07-01 14:03:58.404571910 +0200 -+++ cups-filters-1.0.35/utils/cups-browsed.8 2013-07-01 14:03:58.404571910 +0200 -@@ -0,0 +1,56 @@ -+.\"Text automatically generated by txt2man -+.TH cups-browsed 8 "29 June 2013" "" "" -+.SH NAME -+\fBcups-browsed \fP- A daemon for browsing the Bonjour broadcasts of shared, remote CUPS printers -+\fB -+.SH SYNOPSIS -+.nf -+.fam C -+\fBcups-browsed\fP [\fB-v\fP | \fB-d\fP | \fB--debug\fP] -+ -+.fam T -+.fi -+.fam T -+.fi -+.SH DESCRIPTION -+\fBcups-browsed\fP has three independently switchable functions: -+.IP 1. 4 -+Browse Bonjour broadcasts of remote printers and create/remove local -+raw queues pointing to these printers. -+.IP 2. 4 -+Browse CUPS broadcasts of remote printers and create/remove local raw -+queues pointing to these printers. -+.IP 3. 4 -+Broadcast local queues with the CUPS protocol. -+.SH OPTIONS -+.TP -+.B -+\fB-v\fP, \fB-d\fP, \fB--debug\fP -+Debug mode -+.SH FILES -+/etc/cups/cups-browsed.conf -+.SH NOTES -+Please take references to cups 1.6.x to include newer versions. -+Similarily, cups 1.5.x is intended to encompass older versions too. -+.PP -+In environments with only cups 1.6.x servers and clients (plus -+\fBcups-browsed\fP on either server or client or both) the function described in 1. -+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 -+\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 -+broadcasts from servers with cups 1.5.x. As with browsing of Bonjour -+broadcasts, the created local raw queues are available to applications -+and command line tools. -+.SH SEE ALSO -+ -+\fBcups-browsed.conf\fP(5) -+.PP -+/usr/share/doc/\fBcups-filters\fP/README -+.SH AUTHOR -+The authors of \fBcups-browsed\fP are listed in /usr/share/doc/\fBcups-filters\fP/AUTHORS. -+.PP -+This manual page was written for the Debian Project, but it may be used by others. -diff -up cups-filters-1.0.35/utils/cups-browsed.conf.5.man cups-filters-1.0.35/utils/cups-browsed.conf.5 ---- cups-filters-1.0.35/utils/cups-browsed.conf.5.man 2013-07-01 14:03:58.404571910 +0200 -+++ cups-filters-1.0.35/utils/cups-browsed.conf.5 2013-07-01 14:03:58.404571910 +0200 -@@ -0,0 +1,92 @@ -+.\"Text automatically generated by txt2man -+.TH cups-browsed.conf 5 "29 June 2013" "" "" -+.SH NAME -+\fBcups-browsed.conf \fP- server configuration file for cups-browsed -+\fB -+.SH DESCRIPTION -+The cups-browsed.conf file configures the cups-browsed daemon. It is normally -+located in the /etc/cups directory. Each line in the file can be a -+configuration directive, a blank line, or a comment. Comment lines start -+with the # character. -+.SH DIRECTIVES -+ -+The BrowseAllow directive specifies a system or network to accept -+CUPS browse packets from. The default is to accept browse packets from -+all hosts when BrowseRemoteProtocols uses the CUPS protocol. -+.PP -+.nf -+.fam C -+ BrowseAllow 192.168.7.20 -+ BrowseAllow 192.168.7.0/24 -+ BrowseAllow 192.168.7.0/255.255.255.0 -+ -+ -+.fam T -+.fi -+The BrowsePoll directive polls a server for available printers once -+every 60 seconds. Multiple BrowsePoll directives can be specified -+to poll multiple servers. The default port to connect to is 631. -+BrowsePoll works independently of whether CUPS browsing is activated -+in BrowseRemoteProtocols. -+.PP -+.nf -+.fam C -+ BrowsePoll 192.168.7.20 -+ BrowsePoll 192.168.7.65:631 -+ BrowsePoll host.example.com:631 -+ -+ -+.fam T -+.fi -+The BrowseLocalProtocols directive specifies the protocols to use -+when advertising local shared printers on the network. The default -+is "none". Control of advertising of local shared printers using -+dnssd is done in /etc/cups/cupsd.conf. -+.PP -+.nf -+.fam C -+ BrowseLocalProtocols none -+ BrowseLocalProtocols CUPS -+ -+ -+.fam T -+.fi -+The BrowseRemoteProtocols directive specifies the protocols to use -+when finding remote shared printers on the network. Multiple -+protocols can be specified by separating them with spaces. -+The default is "dnssd cups". -+.PP -+.nf -+.fam C -+ BrowseRemoteProtocols none -+ BrowseRemoteProtocols CUPS dnssd -+ BrowseRemoteProtocols CUPS -+ BrowseRemoteProtocols dnssd -+ -+.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 -+default is "none" for BrowseLocalProtocols and "dnssd cups" for -+BrowseRemoteProtocols. -+.PP -+.nf -+.fam C -+ BrowseProtocols none -+ BrowseProtocols CUPS dnssd -+ BrowseProtocols CUPS -+ BrowseProtocols dnssd -+ -+.fam T -+.fi -+.SH SEE ALSO -+ -+\fBcups-browsed\fP(8) -+.PP -+/usr/share/doc/cups-filters/README -+.SH AUTHOR -+The authors of cups-browsed are listed in /usr/share/doc/cups-filters/AUTHORS. -+.PP -+This manual page was written for the Debian Project, but it may be used by others. diff --git a/SOURCES/cups-filters-manpages.patch b/SOURCES/cups-filters-manpages.patch new file mode 100644 index 0000000..f692331 --- /dev/null +++ b/SOURCES/cups-filters-manpages.patch @@ -0,0 +1,15 @@ +diff --git a/utils/cups-browsed.8 b/utils/cups-browsed.8 +index cc8374c..236f372 100644 +--- a/utils/cups-browsed.8 ++++ b/utils/cups-browsed.8 +@@ -100,8 +100,8 @@ and command line tools. + + \fBcups-browsed.conf\fP(5) + .PP +-/usr/share/doc/\fBcups-browsed\fP/README.gz ++/usr/share/doc/cups-filters-1.0.35/README + .SH AUTHOR +-The authors of \fBcups-browsed\fP are listed in /usr/share/doc/\fBcups-browsed\fP/AUTHORS. ++The authors of \fBcups-browsed\fP are listed in /usr/share/doc/cups-filters-1.0.35/AUTHORS. + .PP + This manual page was written for the Debian Project, but it may be used by others. diff --git a/SPECS/cups-filters.spec b/SPECS/cups-filters.spec index 878656f..77925eb 100644 --- a/SPECS/cups-filters.spec +++ b/SPECS/cups-filters.spec @@ -4,7 +4,7 @@ Summary: OpenPrinting CUPS filters and backends Name: cups-filters Version: 1.0.35 -Release: 22%{?dist} +Release: 26%{?dist} # For a breakdown of the licensing, see COPYING file # GPLv2: filters: commandto*, imagetoraster, pdftops, rasterto*, @@ -20,23 +20,30 @@ License: GPLv2 and GPLv2+ and GPLv3 and GPLv3+ and LGPLv2+ and MIT Group: System Environment/Base Url: http://www.linuxfoundation.org/collaborate/workgroups/openprinting/cups-filters Source0: http://www.openprinting.org/download/cups-filters/cups-filters-%{version}.tar.xz -Source1: cups-browsed.service - -Patch1: cups-filters-man.patch -Patch2: cups-filters-lookup.patch -Patch3: cups-filters-page-label.patch -Patch4: cups-filters-filter-costs.patch -Patch5: cups-filters-urftopdf.patch -Patch6: cups-filters-format-mismatch.patch -Patch7: cups-filters-pdf-landscape.patch -Patch8: cups-filters-pdftoopvp.patch -Patch9: cups-filters-CVE-2013-6475.patch -Patch10: cups-filters-CVE-2014-4337.patch -Patch11: cups-filters-CVE-2014-4338.patch -Patch12: cups-filters-poppler023.patch -Patch13: cups-filters-browsed-underscore.patch -Patch14: cups-filters-browsed-efficiency.patch -Patch15: cups-filters-CVE-2015-3258-3279.patch + +# source files from cups-filters-1.13.4 for partial rebase of cups-browsed and introducing +# implicitclass backend for high availability and load balancing +Source1: backend.tar.gz +Source2: m4.tar.gz +Source3: utils.tar.gz +Source4: configure.ac +Source5: Makefile.am + +Patch1: cups-filters-page-label.patch +Patch2: cups-filters-filter-costs.patch +Patch3: cups-filters-urftopdf.patch +Patch4: cups-filters-format-mismatch.patch +Patch5: cups-filters-pdf-landscape.patch +Patch6: cups-filters-pdftoopvp.patch +Patch7: cups-filters-CVE-2013-6475.patch +Patch8: cups-filters-poppler023.patch +Patch9: cups-filters-CVE-2015-3258-3279.patch +# fixed covscan issues from upstream +Patch10: 0001-Fixing-covscan-issues.patch +# badly fixed coverity issue (bug #1700333) +Patch11: 0001-cups-browsed-Fixed-freeing-of-literal-string-caused-.patch +# bad paths in manpages (bug #1508018) +Patch12: cups-filters-manpages.patch Requires: cups-filters-libs%{?_isa} = %{version}-%{release} @@ -73,6 +80,13 @@ BuildRequires: autoconf BuildRequires: automake BuildRequires: libtool +# gdbus-codegen is used in Makefile.am for generating cups-notifier code, +# so we need glib2-devel +BuildRequires: glib2-devel + +# dbus-devel is needed for new dbus CMS functionality +BuildRequires: dbus-devel + Requires: cups-filesystem Requires: poppler-utils @@ -114,54 +128,51 @@ This package provides cupsfilters and fontembed libraries. This is the development package for OpenPrinting CUPS filters and backends. %prep -%setup -q -%patch1 -p1 -b .man -%patch2 -p1 -b .lookup +# untar m4.tar.gz, backend.tar.gz and utils.tar.gz after untaring main source +# tarball and going into the it +%setup -q -a 1 -a 2 -a 3 + +# copy configure.ac and Makefile.am into untared directory +cp %{SOURCE4} . +cp %{SOURCE5} . # Added support for page-label (bug #987515). -%patch3 -p1 -b .page-label +%patch1 -p1 -b .page-label # Upstream patch to re-work filter costs (bug #998981). -%patch4 -p1 -b .filter-costs +%patch2 -p1 -b .filter-costs # Don't ship urftopdf for now (bug #1002947). -%patch5 -p1 -b .urftopdf +%patch3 -p1 -b .urftopdf # Fixes for some printf-type format mismatches (bug #1003035). -%patch6 -p1 -b .format-mismatch +%patch4 -p1 -b .format-mismatch # Fix PDF landscape printing (bug #1018313). -%patch7 -p1 -b .pdf-landscape +%patch5 -p1 -b .pdf-landscape # Don't ship pdftoopvp for now (bug #1027557). -%patch8 -p1 -b .pdftoopvp +%patch6 -p1 -b .pdftoopvp # Apply CVE-2013-6475 to pdftoopvp even though we don't ship it # (bug #1052741). -%patch9 -p1 -b .CVE-2013-6475 - -# Applied upstream patch for cups-browsed DoS via -# process_browse_data() out-of-bounds read (CVE-2014-4337, -# bug #1111510). -%patch10 -p1 -b .CVE-2014-4337 - -# Applied upstream patch to fix BrowseAllow parsing issue -# (CVE-2014-4338, bug #1091568). -%patch11 -p1 -b .CVE-2014-4338 +%patch7 -p1 -b .CVE-2013-6475 # Build against newer poppler (bug #1217552). -%patch12 -p1 -b .poppler023 - -# Fix cups-browsed "_" handling for printer names (bug #1167408). -%patch13 -p1 -b .browsed-underscore - -# Improve cups-browsed efficiency (bug #1191691). -# Fetch printer descriptions with cups-browsed (bug #1223719). -%patch14 -p1 -b .browsed-efficiency +%patch8 -p1 -b .poppler023 # Fix heap-based buffer overflow in texttopdf filter (bug #1194263, # CVE-2015-3258, CVE-2015-3279). -%patch15 -p1 -b .CVE-2015-3258-3279 +%patch9 -p1 -b .CVE-2015-3258-3279 + +# fixed covscan issues from upstream +%patch10 -p1 -b .covscan + +# 1700333 - [abrt] [faf] cups-filters: raise(): /usr/sbin/cups-browsed killed by 6 +%patch11 -p1 -b .abrt-during-restart + +# 1508018 - man pages: wrong links in man cups-browsed +%patch12 -p1 -b .manpages %build # work-around Rpath @@ -192,7 +203,7 @@ rm -f %{buildroot}%{_bindir}/ttfread # systemd unit file mkdir -p %{buildroot}%{_unitdir} -install -p -m 644 %{SOURCE1} %{buildroot}%{_unitdir} +install -p -m 644 utils/cups-browsed.service %{buildroot}%{_unitdir} %post %systemd_post cups-browsed.service @@ -239,6 +250,7 @@ fi %config(noreplace) %{_sysconfdir}/cups/cups-browsed.conf %attr(0755,root,root) %{_cups_serverbin}/filter/* %attr(0755,root,root) %{_cups_serverbin}/backend/parallel +%attr(0755,root,root) %{_cups_serverbin}/backend/implicitclass # Serial backend needs to run as root (bug #212577#c4). %attr(0700,root,root) %{_cups_serverbin}/backend/serial %{_datadir}/cups/banners @@ -269,6 +281,18 @@ fi %{_libdir}/libfontembed.so %changelog +* Tue May 21 2019 Zdenek Dohnal - 1.0.35-26 +- 1508018 - man pages: wrong links in man cups-browsed + +* Wed Apr 17 2019 Zdenek Dohnal - 1.0.35-25 +- 1700333 - [abrt] [faf] cups-filters: raise(): /usr/sbin/cups-browsed killed by 6 + +* Mon Mar 18 2019 Zdenek Dohnal - 1.0.35-24 +- fixing covscan issues, backported from upstream - 1485502 + +* Wed Feb 20 2019 Zdenek Dohnal - 1.0.35-23 +- 1485502 - Rebase cups-browsed to latest version in upstream cups-filters + * Thu Mar 02 2017 Zdenek Dohnal - 1.0.35-22 - 1427690 - /usr/lib/cups/filter/pstopdf: line 17: which: command not found