From a2326b5b72c5117a00d4342dde8e4d20ff41defe Mon Sep 17 00:00:00 2001 From: msweet Date: Tue, 8 Nov 2011 00:30:03 +0000 Subject: [PATCH] Merge changes from CUPS 1.6svn-r10112. git-svn-id: svn+ssh://src.apple.com/svn/cups/easysw/current@3486 a1ca3aef-8c08-0410-bb20-df032aa958be --- CHANGES-1.5.txt | 14 +- CHANGES-IPPTOOL.txt | 5 +- CHANGES.txt | 9 +- Makedefs.in | 2 - Makefile | 4 +- backend/backend-private.h | 1 + backend/ipp.c | 7 +- backend/snmp-supplies.c | 1 + cgi-bin/admin.c | 153 +- cgi-bin/cgi-private.h | 3 +- config-scripts/cups-common.m4 | 12 +- config-scripts/cups-defaults.m4 | 76 +- config-scripts/cups-gssapi.m4 | 43 +- config-scripts/cups-ldap.m4 | 52 - config-scripts/cups-slp.m4 | 38 - config.h.in | 6 +- configure.in | 4 +- cups/Makefile | 4 +- cups/adminutil.c | 163 +- cups/adminutil.h | 4 +- cups/api-ppd.header | 4 +- cups/api-ppd.shtml | 2 + cups/auth.c | 2 + cups/cups.h | 4 +- cups/encode.c | 16 +- cups/http.c | 541 +-- cups/http.h | 7 +- cups/ipp-private.h | 103 +- cups/ipp-support.c | 407 ++- cups/ipp.c | 4637 ++++++++++++++++++------- cups/ipp.h | 390 +-- cups/language.c | 2 +- cups/libcups_s.exp | 2 - cups/ppd-cache.c | 3 +- cups/ppd.h | 70 +- cups/pwg-media.c | 4 +- cups/testipp.c | 2 +- cups/versioning.h | 4 +- doc/help/api-httpipp.html | 1497 ++++++-- doc/help/api-ppd.html | 8 +- doc/help/man-ipptool.html | 144 + doc/help/man-ipptoolfile.html | 607 ++++ doc/help/ref-cupsd-conf.html.in | 528 +-- doc/help/ref-page_log.html | 2 +- filter/interpret.c | 2 +- filter/raster.c | 24 +- man/cupsd.conf.man.in | 139 +- notifier/mailto.c | 2 +- notifier/rss.c | 3 +- notifier/testnotify.c | 2 +- scheduler/Makefile | 28 +- scheduler/cert.c | 2 +- scheduler/classes.c | 62 +- scheduler/classes.h | 3 +- scheduler/client.c | 2 +- scheduler/conf.c | 583 +--- scheduler/conf.h | 6 - scheduler/cups-driverd.cxx | 14 +- scheduler/cups-polld.c | 469 --- scheduler/dirsvc.c | 5644 ++++--------------------------- scheduler/dirsvc.h | 148 +- scheduler/ipp.c | 389 +-- scheduler/job.c | 22 +- scheduler/main.c | 90 +- scheduler/printers.c | 437 +-- scheduler/printers.h | 7 +- scheduler/server.c | 2 - scheduler/sysman.c | 75 +- scheduler/sysman.h | 10 +- scheduler/testdirsvc.c | 324 -- scheduler/testsub.c | 5 +- systemv/cupsctl.c | 8 - systemv/lpadmin.c | 11 +- systemv/lpstat.c | 3 + templates/admin.tmpl | 11 - test/5.1-lpadmin.sh | 6 +- test/5.2-lpc.sh | 2 +- test/5.3-lpq.sh | 2 +- test/5.4-lpstat.sh | 6 +- test/5.5-lp.sh | 16 +- test/5.6-lpr.sh | 16 +- test/5.7-lprm.sh | 10 +- test/5.8-cancel.sh | 8 +- test/5.9-lpinfo.sh | 8 +- test/ipp-1.1.test | 2 + test/ippserver.c | 200 +- test/ipptool.c | 98 +- test/run-stp-tests.sh | 35 +- vcnet/cups.sln | 10 + vcnet/cupstestppd.vcproj | 46 +- vcnet/ipptool-installer.vdproj | 1551 +++++++++ vcnet/ipptool.vcproj | 46 +- vcnet/testfile.vcproj | 12 +- vcnet/testhttp.vcproj | 12 +- 94 files changed, 9182 insertions(+), 11018 deletions(-) delete mode 100644 config-scripts/cups-ldap.m4 delete mode 100644 config-scripts/cups-slp.m4 create mode 100644 doc/help/man-ipptool.html create mode 100644 doc/help/man-ipptoolfile.html delete mode 100644 scheduler/cups-polld.c delete mode 100644 scheduler/testdirsvc.c create mode 100644 vcnet/ipptool-installer.vdproj diff --git a/CHANGES-1.5.txt b/CHANGES-1.5.txt index 736f43be4..88de1a9d4 100644 --- a/CHANGES-1.5.txt +++ b/CHANGES-1.5.txt @@ -3,7 +3,19 @@ CHANGES-1.5.txt CHANGES IN CUPS V1.5.1 - - Documentation updates (STR #3885, STR #3946) + - Documentation updates (STR #3885, STR #3946, STR #3969) + - Build fixes (STR #3956) + - Group quota ACLs did not work with Kerberos (STR #3972) + - The IPP backend did not retry when a printer responded with + client-error-not-possible (STR #3963) + - PostScript PPDs with filters used the wrong command filter (STR #3973) + - The scheduler incorrectly used free() on a POSIX ACL value, which + could cause a crash (STR #3970) + - PPD files using the MacStandard encoding did not work. + - The web interface did not work on some platforms (STR #3902) + - The lpstat command would crash when then "-u" option was used by a + non-administrator (STR #3953) + - Japanese supply level reporting did not always work. - The DBUS notifier could crash (STR #3947) - Relaxed some of the page size checks in cupstestppd. - The ipptool program now reports attributes that are repeated within diff --git a/CHANGES-IPPTOOL.txt b/CHANGES-IPPTOOL.txt index b7c55a1c8..2d787597b 100644 --- a/CHANGES-IPPTOOL.txt +++ b/CHANGES-IPPTOOL.txt @@ -1,13 +1,14 @@ -CHANGES-IPPTOOL.txt - 2011-10-04 +CHANGES-IPPTOOL.txt - 2011-10-05 -------------------------------- This file provides a list of changes to the ipptool binary distribution posted on cups.org. -2011-10-04 +2011-10-05 - Fixed a crasher bug that showed up on Windows. + - The IPP/1.1 test would hang if the initial Print-Job test failed. - Fixed a typo in the IPP/2.0 test. diff --git a/CHANGES.txt b/CHANGES.txt index 8bca37893..2261b5906 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,8 +1,15 @@ -CHANGES.txt - 1.6b1 - 2011-08-30 +CHANGES.txt - 1.6b1 - 2011-11-03 -------------------------------- CHANGES IN CUPS V1.6b1 + - CUPS no longer supports automatic remote printers or implicit classes + via the CUPS, LDAP, or SLP protocols (STR #3922, STR #3923) + - The PPD APIs are now deprecated and will be removed in a future + version of CUPS (STR #3927) + - The default IPP version for requests is now 2.0 (STR #3929) + - The IPP APIs no longer expose the ipp_t or ipp_attribute_t structures + and instead provide accessor functions (STR #3928) - The scheduler will no longer run programs with group write permission. - The PHP module has been removed (STR #3932) - The bannertops, commandtoescpx, commandtopclx, imagetops, diff --git a/Makedefs.in b/Makedefs.in index b9a97a3b1..e59639e4a 100644 --- a/Makedefs.in +++ b/Makedefs.in @@ -82,10 +82,8 @@ LIBCUPSIMAGE = @LIBCUPSIMAGE@ LIBCUPSMIME = @LIBCUPSMIME@ LIBCUPSPPDC = @LIBCUPSPPDC@ LIBCUPSSTATIC = @LIBCUPSSTATIC@ -LIBLDAP = @LIBLDAP@ LIBMALLOC = @LIBMALLOC@ LIBPAPER = @LIBPAPER@ -LIBSLP = @LIBSLP@ LIBGSSAPI = @LIBGSSAPI@ LIBUSB = @LIBUSB@ LIBWRAP = @LIBWRAP@ diff --git a/Makefile b/Makefile index b7b21698c..6d61c6fba 100644 --- a/Makefile +++ b/Makefile @@ -246,13 +246,13 @@ debugcheck: all unittests # apihelp: - for dir in cgi-bin cups filter driver ppdc scheduler; do\ + for dir in cgi-bin cups filter ppdc scheduler; do\ echo Generating API help in $$dir... ;\ (cd $$dir; $(MAKE) $(MFLAGS) apihelp) || exit 1;\ done framedhelp: - for dir in cgi-bin cups filter driver ppdc scheduler; do\ + for dir in cgi-bin cups filter ppdc scheduler; do\ echo Generating framed API help in $$dir... ;\ (cd $$dir; $(MAKE) $(MFLAGS) framedhelp) || exit 1;\ done diff --git a/backend/backend-private.h b/backend/backend-private.h index 592b1e340..e46973ad0 100644 --- a/backend/backend-private.h +++ b/backend/backend-private.h @@ -274,6 +274,7 @@ extern "C" { #define CUPS_TC_csUTF32 1017 #define CUPS_TC_csUTF32BE 1018 #define CUPS_TC_csUTF32LE 1019 +#define CUPS_TC_csWindows31J 2024 /* diff --git a/backend/ipp.c b/backend/ipp.c index 4ef67a4e2..99df346ae 100644 --- a/backend/ipp.c +++ b/backend/ipp.c @@ -1393,6 +1393,7 @@ main(int argc, /* I - Number of command-line args */ break; if (ipp_status == IPP_SERVICE_UNAVAILABLE || + ipp_status == IPP_NOT_POSSIBLE || ipp_status == IPP_PRINTER_BUSY) { _cupsLangPrintFilter(stderr, "INFO", _("The printer is busy.")); @@ -1550,6 +1551,7 @@ main(int argc, /* I - Number of command-line args */ copies_remaining --; } else if (ipp_status == IPP_SERVICE_UNAVAILABLE || + ipp_status == IPP_NOT_POSSIBLE || ipp_status == IPP_PRINTER_BUSY) continue; else @@ -1622,6 +1624,7 @@ main(int argc, /* I - Number of command-line args */ if (ipp_status > IPP_OK_CONFLICT) { if (ipp_status != IPP_SERVICE_UNAVAILABLE && + ipp_status != IPP_NOT_POSSIBLE && ipp_status != IPP_PRINTER_BUSY) { ippDelete(response); @@ -1669,7 +1672,9 @@ main(int argc, /* I - Number of command-line args */ break; } } - else + else if (ipp_status != IPP_SERVICE_UNAVAILABLE && + ipp_status != IPP_NOT_POSSIBLE && + ipp_status != IPP_PRINTER_BUSY) { /* * If the printer does not return a job-state attribute, it does not diff --git a/backend/snmp-supplies.c b/backend/snmp-supplies.c index 92febb602..b82352063 100644 --- a/backend/snmp-supplies.c +++ b/backend/snmp-supplies.c @@ -801,6 +801,7 @@ backend_walk_cb(cups_snmp_t *packet, /* I - SNMP packet */ break; case CUPS_TC_csShiftJIS : + case CUPS_TC_csWindows31J : /* Close enough for our purposes */ cupsCharsetToUTF8((cups_utf8_t *)supplies[i - 1].name, (char *)packet->object_value.string.bytes, sizeof(supplies[0].name), CUPS_JIS_X0213); diff --git a/cgi-bin/admin.c b/cgi-bin/admin.c index b9963452b..64a29bffd 100644 --- a/cgi-bin/admin.c +++ b/cgi-bin/admin.c @@ -586,8 +586,7 @@ do_am_class(http_t *http, /* I - HTTP connection */ ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_ENUM, "printer-type", CUPS_PRINTER_LOCAL); ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_ENUM, "printer-type-mask", - CUPS_PRINTER_CLASS | CUPS_PRINTER_REMOTE | - CUPS_PRINTER_IMPLICIT); + CUPS_PRINTER_CLASS | CUPS_PRINTER_REMOTE); /* * Do the request and get back a response... @@ -1560,8 +1559,6 @@ do_config_server(http_t *http) /* I - HTTP connection */ const char *debug_logging, /* DEBUG_LOGGING value */ *remote_admin, /* REMOTE_ADMIN value */ *remote_any, /* REMOTE_ANY value */ - *remote_printers, - /* REMOTE_PRINTERS value */ *share_printers,/* SHARE_PRINTERS value */ *user_cancel_any, /* USER_CANCEL_ANY value */ @@ -1577,10 +1574,6 @@ do_config_server(http_t *http) /* I - HTTP connection */ /* MaxJobs value */ *max_log_size = NULL; /* MaxLogSize value */ - char local_protocols[255], - /* BrowseLocalProtocols */ - remote_protocols[255]; - /* BrowseRemoteProtocols */ const char *current_browse_web_if, /* BrowseWebIF value */ *current_preserve_job_history, @@ -1591,12 +1584,8 @@ do_config_server(http_t *http) /* I - HTTP connection */ /* MaxClients value */ *current_max_jobs, /* MaxJobs value */ - *current_max_log_size, + *current_max_log_size; /* MaxLogSize value */ - *current_local_protocols, - /* BrowseLocalProtocols */ - *current_remote_protocols; - /* BrowseRemoteProtocols */ #ifdef HAVE_GSSAPI char default_auth_type[255]; /* DefaultAuthType value */ @@ -1611,7 +1600,6 @@ do_config_server(http_t *http) /* I - HTTP connection */ debug_logging = cgiGetVariable("DEBUG_LOGGING") ? "1" : "0"; remote_admin = cgiGetVariable("REMOTE_ADMIN") ? "1" : "0"; remote_any = cgiGetVariable("REMOTE_ANY") ? "1" : "0"; - remote_printers = cgiGetVariable("REMOTE_PRINTERS") ? "1" : "0"; share_printers = cgiGetVariable("SHARE_PRINTERS") ? "1" : "0"; user_cancel_any = cgiGetVariable("USER_CANCEL_ANY") ? "1" : "0"; @@ -1637,66 +1625,6 @@ do_config_server(http_t *http) /* I - HTTP connection */ if (!max_log_size || atof(max_log_size) <= 0.0) max_log_size = "1m"; - - if (cgiGetVariable("BROWSE_LOCAL_CUPS")) - strcpy(local_protocols, "cups"); - else - local_protocols[0] = '\0'; - -#ifdef HAVE_DNSSD - if (cgiGetVariable("BROWSE_LOCAL_DNSSD")) - { - if (local_protocols[0]) - strcat(local_protocols, " dnssd"); - else - strcat(local_protocols, "dnssd"); - } -#endif /* HAVE_DNSSD */ - -#ifdef HAVE_LDAP - if (cgiGetVariable("BROWSE_LOCAL_LDAP")) - { - if (local_protocols[0]) - strcat(local_protocols, " ldap"); - else - strcat(local_protocols, "ldap"); - } -#endif /* HAVE_LDAP */ - -#ifdef HAVE_LIBSLP - if (cgiGetVariable("BROWSE_LOCAL_SLP")) - { - if (local_protocols[0]) - strcat(local_protocols, " slp"); - else - strcat(local_protocols, "slp"); - } -#endif /* HAVE_SLP */ - - if (cgiGetVariable("BROWSE_REMOTE_CUPS")) - strcpy(remote_protocols, "cups"); - else - remote_protocols[0] = '\0'; - -#ifdef HAVE_LDAP - if (cgiGetVariable("BROWSE_REMOTE_LDAP")) - { - if (remote_protocols[0]) - strcat(remote_protocols, " ldap"); - else - strcat(remote_protocols, "ldap"); - } -#endif /* HAVE_LDAP */ - -#ifdef HAVE_LIBSLP - if (cgiGetVariable("BROWSE_REMOTE_SLP")) - { - if (remote_protocols[0]) - strcat(remote_protocols, " slp"); - else - strcat(remote_protocols, "slp"); - } -#endif /* HAVE_SLP */ } /* @@ -1760,16 +1688,6 @@ do_config_server(http_t *http) /* I - HTTP connection */ settings)) == NULL) current_max_log_size = "1m"; - if ((current_local_protocols = cupsGetOption("BrowseLocalProtocols", - num_settings, - settings)) == NULL) - current_local_protocols = CUPS_DEFAULT_BROWSE_LOCAL_PROTOCOLS; - - if ((current_remote_protocols = cupsGetOption("BrowseRemoteProtocols", - num_settings, - settings)) == NULL) - current_remote_protocols = CUPS_DEFAULT_BROWSE_REMOTE_PROTOCOLS; - /* * See if the settings have changed... */ @@ -1780,8 +1698,6 @@ do_config_server(http_t *http) /* I - HTTP connection */ num_settings, settings)) || strcmp(remote_any, cupsGetOption(CUPS_SERVER_REMOTE_ANY, num_settings, settings)) || - strcmp(remote_printers, cupsGetOption(CUPS_SERVER_REMOTE_PRINTERS, - num_settings, settings)) || strcmp(share_printers, cupsGetOption(CUPS_SERVER_SHARE_PRINTERS, num_settings, settings)) || #ifdef HAVE_GSSAPI @@ -1793,9 +1709,7 @@ do_config_server(http_t *http) /* I - HTTP connection */ num_settings, settings)); if (advanced && !changed) - changed = _cups_strcasecmp(local_protocols, current_local_protocols) || - _cups_strcasecmp(remote_protocols, current_remote_protocols) || - _cups_strcasecmp(browse_web_if, current_browse_web_if) || + changed = _cups_strcasecmp(browse_web_if, current_browse_web_if) || _cups_strcasecmp(preserve_job_history, current_preserve_job_history) || _cups_strcasecmp(preserve_job_files, current_preserve_job_files) || _cups_strcasecmp(max_clients, current_max_clients) || @@ -1817,8 +1731,6 @@ do_config_server(http_t *http) /* I - HTTP connection */ remote_admin, num_settings, &settings); num_settings = cupsAddOption(CUPS_SERVER_REMOTE_ANY, remote_any, num_settings, &settings); - num_settings = cupsAddOption(CUPS_SERVER_REMOTE_PRINTERS, - remote_printers, num_settings, &settings); num_settings = cupsAddOption(CUPS_SERVER_SHARE_PRINTERS, share_printers, num_settings, &settings); num_settings = cupsAddOption(CUPS_SERVER_USER_CANCEL_ANY, @@ -1834,12 +1746,6 @@ do_config_server(http_t *http) /* I - HTTP connection */ * Add advanced settings... */ - if (_cups_strcasecmp(local_protocols, current_local_protocols)) - num_settings = cupsAddOption("BrowseLocalProtocols", local_protocols, - num_settings, &settings); - if (_cups_strcasecmp(remote_protocols, current_remote_protocols)) - num_settings = cupsAddOption("BrowseRemoteProtocols", remote_protocols, - num_settings, &settings); if (_cups_strcasecmp(browse_web_if, current_browse_web_if)) num_settings = cupsAddOption("BrowseWebIF", browse_web_if, num_settings, &settings); @@ -1878,7 +1784,8 @@ do_config_server(http_t *http) /* I - HTTP connection */ else { if (advanced) - cgiSetVariable("refresh_page", "5;URL=/admin/?OP=redirect&URL=/admin/?ADVANCEDSETTINGS=YES"); + cgiSetVariable("refresh_page", "5;URL=/admin/?OP=redirect&" + "URL=/admin/?ADVANCEDSETTINGS=YES"); else cgiSetVariable("refresh_page", "5;URL=/admin/?OP=redirect"); cgiStartHTML(cgiText(_("Change Settings"))); @@ -2359,8 +2266,7 @@ do_export(http_t *http) /* I - HTTP connection */ "printer-type", 0); ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_ENUM, - "printer-type-mask", CUPS_PRINTER_CLASS | CUPS_PRINTER_REMOTE | - CUPS_PRINTER_IMPLICIT); + "printer-type-mask", CUPS_PRINTER_CLASS | CUPS_PRINTER_REMOTE); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, "requested-attributes", NULL, "printer-name"); @@ -2696,10 +2602,6 @@ do_menu(http_t *http) /* I - HTTP connection */ settings)) != NULL && atoi(val)) cgiSetVariable("REMOTE_ANY", "CHECKED"); - if ((val = cupsGetOption(CUPS_SERVER_REMOTE_PRINTERS, num_settings, - settings)) != NULL && atoi(val)) - cgiSetVariable("REMOTE_PRINTERS", "CHECKED"); - if ((val = cupsGetOption(CUPS_SERVER_SHARE_PRINTERS, num_settings, settings)) != NULL && atoi(val)) cgiSetVariable("SHARE_PRINTERS", "CHECKED"); @@ -2722,49 +2624,6 @@ do_menu(http_t *http) /* I - HTTP connection */ cgiSetVariable("HAVE_DNSSD", "1"); #endif /* HAVE_DNSSD */ -#ifdef HAVE_LDAP - cgiSetVariable("HAVE_LDAP", "1"); -#endif /* HAVE_LDAP */ - -#ifdef HAVE_LIBSLP - cgiSetVariable("HAVE_LIBSLP", "1"); -#endif /* HAVE_LIBSLP */ - - if ((val = cupsGetOption("BrowseRemoteProtocols", num_settings, - settings)) == NULL) - if ((val = cupsGetOption("BrowseProtocols", num_settings, - settings)) == NULL) - val = CUPS_DEFAULT_BROWSE_REMOTE_PROTOCOLS; - - if (strstr(val, "cups") || strstr(val, "CUPS")) - cgiSetVariable("BROWSE_REMOTE_CUPS", "CHECKED"); - - if (strstr(val, "ldap") || strstr(val, "LDAP")) - cgiSetVariable("BROWSE_REMOTE_LDAP", "CHECKED"); - - if (strstr(val, "slp") || strstr(val, "SLP")) - cgiSetVariable("BROWSE_REMOTE_SLP", "CHECKED"); - - if ((val = cupsGetOption("BrowseLocalProtocols", num_settings, - settings)) == NULL) - if ((val = cupsGetOption("BrowseProtocols", num_settings, - settings)) == NULL) - val = CUPS_DEFAULT_BROWSE_LOCAL_PROTOCOLS; - - if (strstr(val, "cups") || strstr(val, "CUPS")) - cgiSetVariable("BROWSE_LOCAL_CUPS", "CHECKED"); - - if (strstr(val, "dnssd") || strstr(val, "DNSSD") || - strstr(val, "dns-sd") || strstr(val, "DNS-SD") || - strstr(val, "bonjour") || strstr(val, "BONJOUR")) - cgiSetVariable("BROWSE_LOCAL_DNSSD", "CHECKED"); - - if (strstr(val, "ldap") || strstr(val, "LDAP")) - cgiSetVariable("BROWSE_LOCAL_LDAP", "CHECKED"); - - if (strstr(val, "slp") || strstr(val, "SLP")) - cgiSetVariable("BROWSE_LOCAL_SLP", "CHECKED"); - if ((val = cupsGetOption("BrowseWebIF", num_settings, settings)) == NULL) val = "No"; diff --git a/cgi-bin/cgi-private.h b/cgi-bin/cgi-private.h index fa9bb9b66..412bdc39a 100644 --- a/cgi-bin/cgi-private.h +++ b/cgi-bin/cgi-private.h @@ -3,7 +3,7 @@ * * Private CGI definitions for CUPS. * - * Copyright 2007-2010 by Apple Inc. + * Copyright 2007-2011 by Apple Inc. * Copyright 1997-2006 by Easy Software Products. * * These coded instructions, statements, and computer programs are the @@ -21,6 +21,7 @@ #include #include #include +#include /* TODO: Update so we don't need this */ /* diff --git a/config-scripts/cups-common.m4 b/config-scripts/cups-common.m4 index d7239434b..2417da8f8 100644 --- a/config-scripts/cups-common.m4 +++ b/config-scripts/cups-common.m4 @@ -389,7 +389,17 @@ case $uname in dnl Check for sandbox/Seatbelt support if test $uversion -ge 100; then - AC_CHECK_HEADER(sandbox.h,AC_DEFINE(HAVE_SANDBOX_H)) + AC_CHECK_HEADER(sandbox.h,AC_DEFINE(HAVE_SANDBOX_H)) + fi + if test $uversion -ge 110; then + # Broken public headers in 10.7... + AC_MSG_CHECKING(for sandbox/private.h presence) + if test -f /usr/local/include/sandbox/private.h; then + AC_MSG_RESULT(yes) + else + AC_MSG_RESULT(no) + AC_MSG_ERROR(Run 'sudo mkdir -p /usr/local/include/sandbox' and 'sudo touch /usr/local/include/sandbox/private.h' to build CUPS.) + fi fi dnl Check for XPC support diff --git a/config-scripts/cups-defaults.m4 b/config-scripts/cups-defaults.m4 index eebbb29bb..c223d8db0 100644 --- a/config-scripts/cups-defaults.m4 +++ b/config-scripts/cups-defaults.m4 @@ -64,7 +64,6 @@ AC_ARG_WITH(fatal_errors, [ --with-fatal-errors set default FatalErrors val AC_SUBST(CUPS_FATAL_ERRORS) AC_DEFINE_UNQUOTED(CUPS_DEFAULT_FATAL_ERRORS, "$CUPS_FATAL_ERRORS") - dnl Default LogLevel AC_ARG_WITH(log_level, [ --with-log-level set default LogLevel value, default=warn], CUPS_LOG_LEVEL="$withval", @@ -91,16 +90,16 @@ fi AC_SUBST(CUPS_BROWSING) dnl Default BrowseLocalProtocols -AC_ARG_WITH(local_protocols, [ --with-local-protocols set default BrowseLocalProtocols, default="CUPS"], +AC_ARG_WITH(local_protocols, [ --with-local-protocols set default BrowseLocalProtocols, default=""], default_local_protocols="$withval", default_local_protocols="default") if test x$with_local_protocols != xno; then if test "x$default_local_protocols" = "xdefault"; then if test "x$DNSSDLIBS" != "x"; then - CUPS_BROWSE_LOCAL_PROTOCOLS="CUPS dnssd" - else - CUPS_BROWSE_LOCAL_PROTOCOLS="CUPS" + CUPS_BROWSE_LOCAL_PROTOCOLS="dnssd" + else + CUPS_BROWSE_LOCAL_PROTOCOLS="" fi else CUPS_BROWSE_LOCAL_PROTOCOLS="$default_local_protocols" @@ -113,41 +112,6 @@ AC_SUBST(CUPS_BROWSE_LOCAL_PROTOCOLS) AC_DEFINE_UNQUOTED(CUPS_DEFAULT_BROWSE_LOCAL_PROTOCOLS, "$CUPS_BROWSE_LOCAL_PROTOCOLS") -dnl Default BrowseRemoteProtocols -AC_ARG_WITH(remote_protocols, [ --with-remote-protocols set default BrowseRemoteProtocols, default="CUPS"], - default_remote_protocols="$withval", - default_remote_protocols="default") - -if test x$with_remote_protocols != xno; then - if test "x$default_remote_protocols" = "xdefault"; then - if test "$uname" = "Darwin" -a $uversion -ge 90; then - CUPS_BROWSE_REMOTE_PROTOCOLS="" - else - CUPS_BROWSE_REMOTE_PROTOCOLS="CUPS" - fi - else - CUPS_BROWSE_REMOTE_PROTOCOLS="$default_remote_protocols" - fi -else - CUPS_BROWSE_REMOTE_PROTOCOLS="" -fi - -AC_SUBST(CUPS_BROWSE_REMOTE_PROTOCOLS) -AC_DEFINE_UNQUOTED(CUPS_DEFAULT_BROWSE_REMOTE_PROTOCOLS, - "$CUPS_BROWSE_REMOTE_PROTOCOLS") - -dnl Default BrowseShortNames -AC_ARG_ENABLE(browse_short, [ --disable-browse-short-names - disable BrowseShortNames by default]) -if test "x$enable_browse_short" = xno; then - CUPS_BROWSE_SHORT_NAMES="No" - AC_DEFINE_UNQUOTED(CUPS_DEFAULT_BROWSE_SHORT_NAMES, 0) -else - CUPS_BROWSE_SHORT_NAMES="Yes" - AC_DEFINE_UNQUOTED(CUPS_DEFAULT_BROWSE_SHORT_NAMES, 1) -fi -AC_SUBST(CUPS_BROWSE_SHORT_NAMES) - dnl Default DefaultShared AC_ARG_ENABLE(default_shared, [ --disable-default-shared disable DefaultShared by default]) @@ -160,38 +124,6 @@ else fi AC_SUBST(CUPS_DEFAULT_SHARED) -dnl Default ImplicitClasses -AC_ARG_ENABLE(implicit, [ --disable-implicit-classes - disable ImplicitClasses by default]) -if test "x$enable_implicit" = xno; then - CUPS_IMPLICIT_CLASSES="No" - AC_DEFINE_UNQUOTED(CUPS_DEFAULT_IMPLICIT_CLASSES, 0) -else - CUPS_IMPLICIT_CLASSES="Yes" - AC_DEFINE_UNQUOTED(CUPS_DEFAULT_IMPLICIT_CLASSES, 1) -fi -AC_SUBST(CUPS_IMPLICIT_CLASSES) - -dnl Default UseNetworkDefault -AC_ARG_ENABLE(use_network_default, [ --enable-use-network-default - set UseNetworkDefault to Yes by default]) -if test "x$enable_use_network_default" != xno; then - AC_MSG_CHECKING(whether to use network default printers) - if test "x$enable_use_network_default" = xyes -o $uname != Darwin; then - CUPS_USE_NETWORK_DEFAULT="Yes" - AC_DEFINE_UNQUOTED(CUPS_DEFAULT_USE_NETWORK_DEFAULT, 1) - AC_MSG_RESULT(yes) - else - CUPS_USE_NETWORK_DEFAULT="No" - AC_DEFINE_UNQUOTED(CUPS_DEFAULT_USE_NETWORK_DEFAULT, 0) - AC_MSG_RESULT(no) - fi -else - CUPS_USE_NETWORK_DEFAULT="No" - AC_DEFINE_UNQUOTED(CUPS_DEFAULT_USE_NETWORK_DEFAULT, 0) -fi -AC_SUBST(CUPS_USE_NETWORK_DEFAULT) - dnl Determine the correct username and group for this OS... AC_ARG_WITH(cups_user, [ --with-cups-user set default user for CUPS], CUPS_USER="$withval", diff --git a/config-scripts/cups-gssapi.m4 b/config-scripts/cups-gssapi.m4 index 04977ee64..cf7d58052 100644 --- a/config-scripts/cups-gssapi.m4 +++ b/config-scripts/cups-gssapi.m4 @@ -71,10 +71,45 @@ if test x$enable_gssapi != xno; then if test "x$LIBGSSAPI" != x; then AC_CHECK_HEADER(krb5.h, AC_DEFINE(HAVE_KRB5_H)) if test -d /System/Library/Frameworks/GSS.framework; then - AC_CHECK_HEADER(GSS/gssapi.h, AC_DEFINE(HAVE_GSS_GSSAPI_H)) - AC_CHECK_HEADER(GSS/gssapi_generic.h, AC_DEFINE(HAVE_GSSAPI_GENERIC_H)) - AC_CHECK_HEADER(GSS/gssapi_krb5.h, AC_DEFINE(HAVE_GSSAPI_KRB5_H)) - AC_CHECK_HEADER(GSS/gssapi_spi.h, AC_DEFINE(HAVE_GSS_GSSAPI_SPI_H)) + gssdir="/System/Library/Frameworks/GSS.framework" + AC_MSG_CHECKING(for GSS/gssapi.h presence) + if test -f $gssdir/Headers/gssapi.h; then + AC_DEFINE(HAVE_GSS_GSSAPI_H) + AC_MSG_RESULT(yes) + else + AC_MSG_RESULT(no) + fi + AC_MSG_CHECKING(for GSS/gssapi_generic.h presence) + if test -f $gssdir/Headers/gssapi_generic.h; then + AC_DEFINE(HAVE_GSSAPI_GENERIC_H) + AC_MSG_RESULT(yes) + else + AC_MSG_RESULT(no) + fi + AC_MSG_CHECKING(for GSS/gssapi_krb5.h presence) + if test -f $gssdir/Headers/gssapi_krb5.h; then + AC_DEFINE(HAVE_GSSAPI_KRB5_H) + AC_MSG_RESULT(yes) + else + AC_MSG_RESULT(no) + fi + AC_MSG_CHECKING(for GSS/gssapi_spi.h presence) + if test -f $gssdir/PrivateHeaders/gssapi_spi.h; then + AC_MSG_RESULT(yes) + AC_MSG_CHECKING(for GSS/gssapi_spi.h usability) + if test -s $gssdir/PrivateHeaders/gssapi_spi.h; then + AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_GSS_GSSAPI_SPI_H) + else + AC_MSG_RESULT(no) + fi + else + AC_MSG_RESULT(no) + if test $uversion -ge 110; then + # Broken public headers in 10.7... + AC_MSG_ERROR(Run 'sudo mkdir -p $gssdir/PrivateHeaders' and 'sudo touch $gssdir/PrivateHeaders/gssapi_spi.h' to build CUPS.) + fi + fi else AC_CHECK_HEADER(gssapi.h, AC_DEFINE(HAVE_GSSAPI_H)) AC_CHECK_HEADER(gssapi/gssapi.h, AC_DEFINE(HAVE_GSSAPI_GSSAPI_H)) diff --git a/config-scripts/cups-ldap.m4 b/config-scripts/cups-ldap.m4 deleted file mode 100644 index 16c017ce4..000000000 --- a/config-scripts/cups-ldap.m4 +++ /dev/null @@ -1,52 +0,0 @@ -dnl -dnl "$Id: cups-ldap.m4 7800 2008-07-25 21:01:34Z mike $" -dnl -dnl LDAP configuration stuff for CUPS. -dnl -dnl Copyright 2007-2011 by Apple Inc. -dnl Copyright 2003-2006 by Easy Software Products, all rights reserved. -dnl -dnl These coded instructions, statements, and computer programs are the -dnl property of Apple Inc. and are protected by Federal copyright -dnl law. Distribution and use rights are outlined in the file "LICENSE.txt" -dnl which should have been included with this file. If this file is -dnl file is missing or damaged, see the license at "http://www.cups.org/". -dnl - -AC_ARG_ENABLE(ldap, [ --disable-ldap disable LDAP support]) -AC_ARG_WITH(ldap-libs, [ --with-ldap-libs set directory for LDAP library], - LDFLAGS="-L$withval $LDFLAGS" - DSOFLAGS="-L$withval $DSOFLAGS",) -AC_ARG_WITH(ldap-includes, [ --with-ldap-includes set directory for LDAP includes], - CFLAGS="-I$withval $CFLAGS" - CPPFLAGS="-I$withval $CPPFLAGS",) - -LIBLDAP="" - -if test x$enable_ldap != xno; then - AC_CHECK_HEADER(ldap.h, [ - AC_CHECK_LIB(ldap, ldap_initialize, - AC_DEFINE(HAVE_LDAP) - AC_DEFINE(HAVE_OPENLDAP) - LIBLDAP="-lldap" - AC_CHECK_LIB(ldap, ldap_start_tls, - AC_DEFINE(HAVE_LDAP_SSL)), - - AC_CHECK_LIB(ldap, ldap_init, - AC_DEFINE(HAVE_LDAP) - AC_DEFINE(HAVE_MOZILLA_LDAP) - LIBLDAP="-lldap" - AC_CHECK_HEADER(ldap_ssl.h, AC_DEFINE(HAVE_LDAP_SSL_H),,[#include ]) - AC_CHECK_LIB(ldap, ldapssl_init, - AC_DEFINE(HAVE_LDAP_SSL))) - ) - AC_CHECK_LIB(ldap, ldap_set_rebind_proc, AC_DEFINE(HAVE_LDAP_REBIND_PROC)) - ]) -fi - -AC_SUBST(LIBLDAP) - - -dnl -dnl End of "$Id: cups-ldap.m4 7800 2008-07-25 21:01:34Z mike $". -dnl diff --git a/config-scripts/cups-slp.m4 b/config-scripts/cups-slp.m4 deleted file mode 100644 index fdf1b4338..000000000 --- a/config-scripts/cups-slp.m4 +++ /dev/null @@ -1,38 +0,0 @@ -dnl -dnl "$Id: cups-slp.m4 7241 2008-01-22 22:34:52Z mike $" -dnl -dnl OpenSLP configuration stuff for CUPS. -dnl -dnl Copyright 2007-2011 by Apple Inc. -dnl Copyright 1997-2005 by Easy Software Products, all rights reserved. -dnl -dnl These coded instructions, statements, and computer programs are the -dnl property of Apple Inc. and are protected by Federal copyright -dnl law. Distribution and use rights are outlined in the file "LICENSE.txt" -dnl which should have been included with this file. If this file is -dnl file is missing or damaged, see the license at "http://www.cups.org/". -dnl - -AC_ARG_ENABLE(slp, [ --disable-slp disable SLP support]) -AC_ARG_WITH(openslp-libs, [ --with-openslp-libs set directory for OpenSLP library], - LDFLAGS="-L$withval $LDFLAGS" - DSOFLAGS="-L$withval $DSOFLAGS",) -AC_ARG_WITH(openslp-includes, [ --with-openslp-includes set directory for OpenSLP includes], - CFLAGS="-I$withval $CFLAGS" - CPPFLAGS="-I$withval $CPPFLAGS",) - -LIBSLP="" - -if test x$enable_slp != xno; then - AC_CHECK_HEADER(slp.h, - AC_CHECK_LIB(slp, SLPOpen, - AC_DEFINE(HAVE_LIBSLP) - LIBSLP="-lslp")) -fi - -AC_SUBST(LIBSLP) - - -dnl -dnl End of "$Id: cups-slp.m4 7241 2008-01-22 22:34:52Z mike $". -dnl diff --git a/config.h.in b/config.h.in index 188b7527f..a3500c930 100644 --- a/config.h.in +++ b/config.h.in @@ -62,12 +62,8 @@ */ #define CUPS_DEFAULT_BROWSING 1 -#define CUPS_DEFAULT_BROWSE_LOCAL_PROTOCOLS "CUPS" -#define CUPS_DEFAULT_BROWSE_REMOTE_PROTOCOLS "CUPS" -#define CUPS_DEFAULT_BROWSE_SHORT_NAMES 1 +#define CUPS_DEFAULT_BROWSE_LOCAL_PROTOCOLS "" #define CUPS_DEFAULT_DEFAULT_SHARED 1 -#define CUPS_DEFAULT_IMPLICIT_CLASSES 1 -#define CUPS_DEFAULT_USE_NETWORK_DEFAULT 1 /* diff --git a/configure.in b/configure.in index 60702956a..f35274b02 100644 --- a/configure.in +++ b/configure.in @@ -3,7 +3,7 @@ dnl "$Id: configure.in 7833 2008-08-04 20:55:13Z mike $" dnl dnl Configuration script for CUPS. dnl -dnl Copyright 2007-2010 by Apple Inc. +dnl Copyright 2007-2011 by Apple Inc. dnl Copyright 1997-2007 by Easy Software Products, all rights reserved. dnl dnl These coded instructions, statements, and computer programs are the @@ -27,9 +27,7 @@ sinclude(config-scripts/cups-compiler.m4) sinclude(config-scripts/cups-network.m4) sinclude(config-scripts/cups-poll.m4) -sinclude(config-scripts/cups-slp.m4) sinclude(config-scripts/cups-gssapi.m4) -sinclude(config-scripts/cups-ldap.m4) sinclude(config-scripts/cups-threads.m4) sinclude(config-scripts/cups-ssl.m4) sinclude(config-scripts/cups-pam.m4) diff --git a/cups/Makefile b/cups/Makefile index 0924e144d..be6bd4299 100644 --- a/cups/Makefile +++ b/cups/Makefile @@ -586,7 +586,7 @@ apihelp: file.h file.c dir.h dir.c >../doc/help/api-filedir.html mxmldoc --tokens api-filedir.xml >../doc/help/api-filedir.tokens $(RM) api-filedir.xml - mxmldoc --section "Programming" --title "PPD API" \ + mxmldoc --section "Programming" --title "PPD API (DEPRECATED)" \ --css ../doc/cups-printable.css \ --header api-ppd.header --intro api-ppd.shtml \ api-ppd.xml \ @@ -638,7 +638,7 @@ framedhelp: --header api-filedir.header --intro api-filedir.shtml \ file.h file.c dir.h dir.c mxmldoc --framed api-ppd \ - --section "Programming" --title "PPD API" \ + --section "Programming" --title "PPD API (DEPRECATED)" \ --css ../doc/cups-printable.css \ --header api-ppd.header --intro api-ppd.shtml \ ppd.h attr.c conflicts.c custom.c emit.c localize.c mark.c \ diff --git a/cups/adminutil.c b/cups/adminutil.c index 04b8e8fd2..ee6f47ea3 100644 --- a/cups/adminutil.c +++ b/cups/adminutil.c @@ -970,8 +970,6 @@ cupsAdminGetServerSettings( remote_admin = 0, /* Remote administration allowed? */ remote_any = 0, /* Remote access from anywhere allowed? */ browsing = 1, /* Browsing enabled? */ - browse_allow = 1, /* Browse address set? */ - browse_address = 0, /* Browse address set? */ cancel_policy = 1, /* Cancel-job policy set? */ debug_logging = 0; /* LogLevel debug set? */ int linenum = 0, /* Line number in file */ @@ -1020,26 +1018,16 @@ cupsAdminGetServerSettings( } else if (!_cups_strcasecmp(line, "Browsing")) { - browsing = !_cups_strcasecmp(value, "yes") || !_cups_strcasecmp(value, "on") || + browsing = !_cups_strcasecmp(value, "yes") || + !_cups_strcasecmp(value, "on") || !_cups_strcasecmp(value, "true"); } - else if (!_cups_strcasecmp(line, "BrowseAddress")) - { - browse_address = 1; - } - else if (!_cups_strcasecmp(line, "BrowseAllow")) - { - browse_allow = 1; - } - else if (!_cups_strcasecmp(line, "BrowseOrder")) - { - browse_allow = !_cups_strncasecmp(value, "deny,", 5); - } else if (!_cups_strcasecmp(line, "LogLevel")) { debug_logging = !_cups_strncasecmp(value, "debug", 5); } - else if (!_cups_strcasecmp(line, "cupsd_num_settings, &(cg->cupsd_settings)); - cg->cupsd_num_settings = cupsAddOption(CUPS_SERVER_REMOTE_PRINTERS, - (browsing && browse_allow) ? - "1" : "0", - cg->cupsd_num_settings, - &(cg->cupsd_settings)); - cg->cupsd_num_settings = cupsAddOption(CUPS_SERVER_SHARE_PRINTERS, - (remote_access && browsing && - browse_address) ? "1" : "0", + (remote_access && browsing) ? "1" : + "0", cg->cupsd_num_settings, &(cg->cupsd_settings)); @@ -1204,8 +1188,7 @@ cupsAdminSetServerSettings( in_conf_location, /* In the /admin/conf location? */ in_root_location; /* In the / location? */ const char *val; /* Setting value */ - int remote_printers, /* Show remote printers */ - share_printers, /* Share local printers */ + int share_printers, /* Share local printers */ remote_admin, /* Remote administration allowed? */ remote_any, /* Remote access from anywhere? */ user_cancel_any, /* Cancel-job policy set? */ @@ -1219,8 +1202,7 @@ cupsAdminSetServerSettings( wrote_root_location; /* Wrote the / location? */ int indent; /* Indentation */ int cupsd_num_settings; /* New number of settings */ - int old_remote_printers, /* Show remote printers */ - old_share_printers, /* Share local printers */ + int old_share_printers, /* Share local printers */ old_remote_admin, /* Remote administration allowed? */ old_user_cancel_any, /* Cancel-job policy set? */ old_debug_logging; /* LogLevel debug set? */ @@ -1294,15 +1276,6 @@ cupsAdminSetServerSettings( DEBUG_printf(("1cupsAdminSetServerSettings: old remote_any=%d", remote_any)); - if ((val = cupsGetOption(CUPS_SERVER_REMOTE_PRINTERS, cupsd_num_settings, - cupsd_settings)) != NULL) - old_remote_printers = atoi(val); - else - old_remote_printers = 1; - - DEBUG_printf(("1cupsAdminSetServerSettings: old remote_printers=%d", - old_remote_printers)); - if ((val = cupsGetOption(CUPS_SERVER_SHARE_PRINTERS, cupsd_num_settings, cupsd_settings)) != NULL) old_share_printers = atoi(val); @@ -1374,26 +1347,6 @@ cupsAdminSetServerSettings( DEBUG_printf(("1cupsAdminSetServerSettings: remote_admin=%d", remote_admin)); - if ((val = cupsGetOption(CUPS_SERVER_REMOTE_PRINTERS, num_settings, - settings)) != NULL) - { - remote_printers = atoi(val); - - if (remote_printers == old_remote_printers) - { - /* - * No change to this setting... - */ - - remote_printers = -1; - } - } - else - remote_printers = -1; - - DEBUG_printf(("1cupsAdminSetServerSettings: remote_printers=%d", - remote_printers)); - if ((val = cupsGetOption(CUPS_SERVER_SHARE_PRINTERS, num_settings, settings)) != NULL) { @@ -1517,80 +1470,33 @@ cupsAdminSetServerSettings( cupsFilePrintf(temp, "Listen %s\n", value); } else if ((!_cups_strcasecmp(line, "Browsing") || - !_cups_strcasecmp(line, "BrowseAddress") || - !_cups_strcasecmp(line, "BrowseAllow") || - !_cups_strcasecmp(line, "BrowseDeny") || - !_cups_strcasecmp(line, "BrowseLocalProtocols") || - !_cups_strcasecmp(line, "BrowseRemoteProtocols") || - !_cups_strcasecmp(line, "BrowseOrder")) && - (remote_printers >= 0 || share_printers >= 0)) + !_cups_strcasecmp(line, "BrowseLocalProtocols")) && + share_printers >= 0) { if (!wrote_browsing) { - int new_remote_printers = (remote_printers > 0 || - (remote_printers == -1 && - old_remote_printers > 0)); int new_share_printers = (share_printers > 0 || (share_printers == -1 && old_share_printers > 0)); wrote_browsing = 1; - if (new_remote_printers || new_share_printers) + if (new_share_printers) { const char *localp = cupsGetOption("BrowseLocalProtocols", num_settings, settings); - const char *remotep = cupsGetOption("BrowseRemoteProtocols", - num_settings, settings); if (!localp || !localp[0]) localp = cupsGetOption("BrowseLocalProtocols", cupsd_num_settings, cupsd_settings); - if (!remotep) - remotep = cupsGetOption("BrowseRemoteProtocols", cupsd_num_settings, - cupsd_settings); - - if (new_remote_printers && new_share_printers) - cupsFilePuts(temp, - "# Enable printer sharing and shared printers.\n"); - else if (new_remote_printers) - cupsFilePuts(temp, - "# Show shared printers on the local network.\n"); - else - cupsFilePuts(temp, - "# Share local printers on the local network.\n"); - + cupsFilePuts(temp, "# Share local printers on the local network.\n"); cupsFilePuts(temp, "Browsing On\n"); - cupsFilePuts(temp, "BrowseOrder allow,deny\n"); - - if (new_remote_printers) - { - cupsFilePuts(temp, "BrowseAllow all\n"); - - if (!remotep) - remotep = CUPS_DEFAULT_BROWSE_REMOTE_PROTOCOLS; - - cupsFilePrintf(temp, "BrowseRemoteProtocols %s\n", remotep); - } - else - cupsFilePuts(temp, "BrowseRemoteProtocols\n"); - cupsd_num_settings = cupsAddOption("BrowseRemoteProtocols", remotep, - cupsd_num_settings, - &cupsd_settings); + if (!localp) + localp = CUPS_DEFAULT_BROWSE_LOCAL_PROTOCOLS; - if (new_share_printers) - { - cupsFilePuts(temp, "BrowseAddress @LOCAL\n"); - - if (!localp) - localp = CUPS_DEFAULT_BROWSE_LOCAL_PROTOCOLS; - - cupsFilePrintf(temp, "BrowseLocalProtocols %s\n", localp); - } - else - cupsFilePuts(temp, "BrowseLocalProtocols\n"); + cupsFilePrintf(temp, "BrowseLocalProtocols %s\n", localp); cupsd_num_settings = cupsAddOption("BrowseLocalProtocols", localp, cupsd_num_settings, @@ -1598,8 +1504,7 @@ cupsAdminSetServerSettings( } else { - cupsFilePuts(temp, - "# Disable printer sharing and shared printers.\n"); + cupsFilePuts(temp, "# Disable printer sharing.\n"); cupsFilePuts(temp, "Browsing Off\n"); } } @@ -1865,25 +1770,12 @@ cupsAdminSetServerSettings( * Write any missing info... */ - if (!wrote_browsing && (remote_printers >= 0 || share_printers >= 0)) + if (!wrote_browsing && share_printers >= 0) { - if (remote_printers > 0 || share_printers > 0) + if (share_printers > 0) { - if (remote_printers > 0 && share_printers > 0) - cupsFilePuts(temp, "# Enable printer sharing and shared printers.\n"); - else if (remote_printers > 0) - cupsFilePuts(temp, "# Show shared printers on the local network.\n"); - else - cupsFilePuts(temp, "# Share local printers on the local network.\n"); - + cupsFilePuts(temp, "# Share local printers on the local network.\n"); cupsFilePuts(temp, "Browsing On\n"); - cupsFilePuts(temp, "BrowseOrder allow,deny\n"); - - if (remote_printers > 0) - cupsFilePuts(temp, "BrowseAllow all\n"); - - if (share_printers > 0) - cupsFilePuts(temp, "BrowseAddress @LOCAL\n"); } else { @@ -2090,15 +1982,6 @@ cupsAdminSetServerSettings( remote_any ? "1" : "0", cupsd_num_settings, &cupsd_settings); - if (remote_printers >= 0) - cupsd_num_settings = cupsAddOption(CUPS_SERVER_REMOTE_PRINTERS, - remote_printers ? "1" : "0", - cupsd_num_settings, &cupsd_settings); - else - cupsd_num_settings = cupsAddOption(CUPS_SERVER_REMOTE_PRINTERS, - old_remote_printers ? "1" : "0", - cupsd_num_settings, &cupsd_settings); - if (share_printers >= 0) cupsd_num_settings = cupsAddOption(CUPS_SERVER_SHARE_PRINTERS, share_printers ? "1" : "0", diff --git a/cups/adminutil.h b/cups/adminutil.h index f05691677..14c681b16 100644 --- a/cups/adminutil.h +++ b/cups/adminutil.h @@ -3,7 +3,7 @@ * * Administration utility API definitions for CUPS. * - * Copyright 2007-2010 by Apple Inc. + * Copyright 2007-2011 by Apple Inc. * Copyright 2001-2007 by Easy Software Products. * * These coded instructions, statements, and computer programs are the @@ -42,7 +42,7 @@ extern "C" { # define CUPS_SERVER_DEBUG_LOGGING "_debug_logging" # define CUPS_SERVER_REMOTE_ADMIN "_remote_admin" # define CUPS_SERVER_REMOTE_ANY "_remote_any" -# define CUPS_SERVER_REMOTE_PRINTERS "_remote_printers" +/*# define CUPS_SERVER_REMOTE_PRINTERS "_remote_printers"*/ # define CUPS_SERVER_SHARE_PRINTERS "_share_printers" # define CUPS_SERVER_USER_CANCEL_ANY "_user_cancel_any" diff --git a/cups/api-ppd.header b/cups/api-ppd.header index 9809c8698..9eae26b48 100644 --- a/cups/api-ppd.header +++ b/cups/api-ppd.header @@ -12,7 +12,9 @@ file is missing or damaged, see the license at "http://www.cups.org/". --> -

PPD API

+

PPD API (DEPRECATED)

+ +
The PPD API is deprecated starting in CUPS 1.6. Please use the new Job Ticket APIs in the CUPS API documentation. These functions will be removed in a future release of CUPS.
diff --git a/cups/api-ppd.shtml b/cups/api-ppd.shtml index ade717caf..a8ecc095c 100644 --- a/cups/api-ppd.shtml +++ b/cups/api-ppd.shtml @@ -15,6 +15,8 @@

Overview

+
The PPD API is deprecated starting in CUPS 1.6. Please use the new Job Ticket APIs in the CUPS API documentation. These functions will be removed in a future release of CUPS.
+

The CUPS PPD API provides read-only access the data in PostScript Printer Description ("PPD") files which are used for all printers with a driver. With it you can obtain the data necessary to display printer options to users, mark diff --git a/cups/auth.c b/cups/auth.c index 1351581e0..bea62b797 100644 --- a/cups/auth.c +++ b/cups/auth.c @@ -65,6 +65,8 @@ extern const char *cssmErrorString(int error); # ifdef HAVE_GSS_GSSAPI_SPI_H # include # else +# define GSS_AUTH_IDENTITY_TYPE_1 1 +# define gss_acquire_cred_ex_f __ApplePrivate_gss_acquire_cred_ex_f typedef struct gss_auth_identity { uint32_t type; diff --git a/cups/cups.h b/cups/cups.h index 0a123c728..cb82ddfc0 100644 --- a/cups/cups.h +++ b/cups/cups.h @@ -97,7 +97,7 @@ enum cups_ptype_e /**** Printer type/capability bit constants ****/ CUPS_PRINTER_MEDIUM = 0x2000, /* Can do Tabloid/B/C/A3/A2 */ CUPS_PRINTER_LARGE = 0x4000, /* Can do D/E/A1/A0 */ CUPS_PRINTER_VARIABLE = 0x8000, /* Can do variable sizes */ - CUPS_PRINTER_IMPLICIT = 0x10000, /* Implicit class */ + CUPS_PRINTER_IMPLICIT = 0x10000, /* Implicit class @private@ @since Deprecated@ */ CUPS_PRINTER_DEFAULT = 0x20000, /* Default printer on network */ CUPS_PRINTER_FAX = 0x40000, /* Fax queue */ CUPS_PRINTER_REJECTING = 0x80000, /* Printer is rejecting jobs */ @@ -105,7 +105,7 @@ enum cups_ptype_e /**** Printer type/capability bit constants ****/ CUPS_PRINTER_NOT_SHARED = 0x200000, /* Printer is not shared @since CUPS 1.2/Mac OS X 10.5@ */ CUPS_PRINTER_AUTHENTICATED = 0x400000,/* Printer requires authentication @since CUPS 1.2/Mac OS X 10.5@ */ CUPS_PRINTER_COMMANDS = 0x800000, /* Printer supports maintenance commands @since CUPS 1.2/Mac OS X 10.5@ */ - CUPS_PRINTER_DISCOVERED = 0x1000000, /* Printer was automatically discovered and added @since CUPS 1.3/Mac OS X 10.5@ */ + CUPS_PRINTER_DISCOVERED = 0x1000000, /* Printer was automatically discovered and added @private@ @since Deprecated@ */ CUPS_PRINTER_SCANNER = 0x2000000, /* Scanner-only device @since CUPS 1.4/Mac OS X 10.6@ */ CUPS_PRINTER_MFP = 0x4000000, /* Printer with scanning capabilities @since CUPS 1.4/Mac OS X 10.6@ */ CUPS_PRINTER_OPTIONS = 0x6fffc /* ~(CLASS | REMOTE | IMPLICIT | DEFAULT | FAX | REJECTING | DELETE | NOT_SHARED | AUTHENTICATED | COMMANDS | DISCOVERED) @private@ */ diff --git a/cups/encode.c b/cups/encode.c index 0f2dd38cf..e2c092232 100644 --- a/cups/encode.c +++ b/cups/encode.c @@ -343,7 +343,8 @@ cupsEncodeOptions2( * Allocate memory for the attribute values... */ - if ((attr = _ippAddAttr(ipp, count)) == NULL) + if ((attr = ippAddStrings(ipp, group_tag, value_tag, option->name, count, + NULL, NULL)) == NULL) { /* * Ran out of memory! @@ -353,19 +354,6 @@ cupsEncodeOptions2( return; } - /* - * Now figure out what type of value we have... - */ - - attr->group_tag = group_tag; - attr->value_tag = value_tag; - - /* - * Copy the name over... - */ - - attr->name = _cupsStrAlloc(option->name); - if (count > 1) { /* diff --git a/cups/http.c b/cups/http.c index 160a09d07..2ea99bee1 100644 --- a/cups/http.c +++ b/cups/http.c @@ -19,103 +19,103 @@ * * Contents: * - * httpAddCredential() - Allocates and adds a single credential to an - * array. - * _httpBIOMethods() - Get the OpenSSL BIO methods for HTTP - * connections. - * httpBlocking() - Set blocking/non-blocking behavior on a - * connection. - * httpCheck() - Check to see if there is a pending response - * from the server. - * httpClearCookie() - Clear the cookie value(s). - * httpClearFields() - Clear HTTP request fields. - * httpClose() - Close an HTTP connection. - * httpConnect() - Connect to a HTTP server. - * httpConnectEncrypt() - Connect to a HTTP server using encryption. - * httpCopyCredentials() - Copy the credentials associated with an - * encrypted connection. - * _httpCreate() - Create an unconnected HTTP connection. - * _httpCreateCredentials() - Create credentials in the internal format. - * httpDelete() - Send a DELETE request to the server. - * _httpDisconnect() - Disconnect a HTTP connection. - * httpEncryption() - Set the required encryption on the link. - * httpError() - Get the last error on a connection. - * httpFlush() - Flush data from a HTTP connection. - * httpFlushWrite() - Flush data in write buffer. - * _httpFreeCredentials() - Free internal credentials. - * httpFreeCredentials() - Free an array of credentials. - * httpGet() - Send a GET request to the server. - * httpGetAuthString() - Get the current authorization string. - * httpGetBlocking() - Get the blocking/non-block state of a - * connection. - * httpGetCookie() - Get any cookie data from the response. - * httpGetFd() - Get the file descriptor associated with a - * connection. - * httpGetField() - Get a field value from a request/response. - * httpGetLength() - Get the amount of data remaining from the - * content-length or transfer-encoding fields. - * httpGetLength2() - Get the amount of data remaining from the - * content-length or transfer-encoding fields. - * httpGetStatus() - Get the status of the last HTTP request. - * httpGetSubField() - Get a sub-field value. - * httpGetSubField2() - Get a sub-field value. - * httpGets() - Get a line of text from a HTTP connection. - * httpHead() - Send a HEAD request to the server. - * httpInitialize() - Initialize the HTTP interface library and set - * the default HTTP proxy (if any). - * httpOptions() - Send an OPTIONS request to the server. - * _httpPeek() - Peek at data from a HTTP connection. - * httpPost() - Send a POST request to the server. - * httpPrintf() - Print a formatted string to a HTTP connection. - * httpPut() - Send a PUT request to the server. - * httpRead() - Read data from a HTTP connection. - * httpRead2() - Read data from a HTTP connection. - * _httpReadCDSA() - Read function for the CDSA library. - * _httpReadGNUTLS() - Read function for the GNU TLS library. - * httpReconnect() - Reconnect to a HTTP server. - * httpSetAuthString() - Set the current authorization string. - * httpSetCredentials() - Set the credentials associated with an - * encrypted connection. - * httpSetCookie() - Set the cookie value(s). - * httpSetExpect() - Set the Expect: header in a request. - * httpSetField() - Set the value of an HTTP header. - * httpSetLength() - Set the content-length and content-encoding. - * httpSetTimeout() - Set read/write timeouts and an optional - * callback. - * httpTrace() - Send an TRACE request to the server. - * _httpUpdate() - Update the current HTTP status for incoming - * data. - * httpUpdate() - Update the current HTTP state for incoming - * data. - * _httpWait() - Wait for data available on a connection (no - * flush). - * httpWait() - Wait for data available on a connection. - * httpWrite() - Write data to a HTTP connection. - * httpWrite2() - Write data to a HTTP connection. - * _httpWriteCDSA() - Write function for the CDSA library. - * _httpWriteGNUTLS() - Write function for the GNU TLS library. - * http_bio_ctrl() - Control the HTTP connection. - * http_bio_free() - Free OpenSSL data. - * http_bio_new() - Initialize an OpenSSL BIO structure. - * http_bio_puts() - Send a string for OpenSSL. - * http_bio_read() - Read data for OpenSSL. - * http_bio_write() - Write data for OpenSSL. - * http_debug_hex() - Do a hex dump of a buffer. - * http_field() - Return the field index for a field name. - * http_read_ssl() - Read from a SSL/TLS connection. - * http_locking_cb() - Lock/unlock a thread's mutex. - * http_send() - Send a request with all fields and the trailing - * blank line. - * http_set_credentials() - Set the SSL/TLS credentials. - * http_set_timeout() - Set the socket timeout values. - * http_set_wait() - Set the default wait value for reads. - * http_setup_ssl() - Set up SSL/TLS support on a connection. - * http_shutdown_ssl() - Shut down SSL/TLS on a connection. - * http_threadid_cb() - Return the current thread ID. - * http_upgrade() - Force upgrade to TLS encryption. - * http_write() - Write a buffer to a HTTP connection. - * http_write_chunk() - Write a chunked buffer. - * http_write_ssl() - Write to a SSL/TLS connection. + * httpAddCredential() - Allocates and adds a single credential to an + * array. + * _httpBIOMethods() - Get the OpenSSL BIO methods for HTTP + * connections. + * httpBlocking() - Set blocking/non-blocking behavior on a + * connection. + * httpCheck() - Check to see if there is a pending response + * from the server. + * httpClearCookie() - Clear the cookie value(s). + * httpClearFields() - Clear HTTP request fields. + * httpClose() - Close an HTTP connection. + * httpConnect() - Connect to a HTTP server. + * httpConnectEncrypt() - Connect to a HTTP server using encryption. + * httpCopyCredentials() - Copy the credentials associated with an + * encrypted connection. + * _httpCreate() - Create an unconnected HTTP connection. + * _httpCreateCredentials() - Create credentials in the internal format. + * httpDelete() - Send a DELETE request to the server. + * _httpDisconnect() - Disconnect a HTTP connection. + * httpEncryption() - Set the required encryption on the link. + * httpError() - Get the last error on a connection. + * httpFlush() - Flush data from a HTTP connection. + * httpFlushWrite() - Flush data in write buffer. + * _httpFreeCredentials() - Free internal credentials. + * httpFreeCredentials() - Free an array of credentials. + * httpGet() - Send a GET request to the server. + * httpGetAuthString() - Get the current authorization string. + * httpGetBlocking() - Get the blocking/non-block state of a + * connection. + * httpGetCookie() - Get any cookie data from the response. + * httpGetFd() - Get the file descriptor associated with a + * connection. + * httpGetField() - Get a field value from a request/response. + * httpGetLength() - Get the amount of data remaining from the + * content-length or transfer-encoding fields. + * httpGetLength2() - Get the amount of data remaining from the + * content-length or transfer-encoding fields. + * httpGets() - Get a line of text from a HTTP connection. + * httpGetState() - Get the current state of the HTTP request. + * httpGetStatus() - Get the status of the last HTTP request. + * httpGetSubField() - Get a sub-field value. + * httpGetSubField2() - Get a sub-field value. + * httpGetVersion() - Get the HTTP version at the other end. + * httpHead() - Send a HEAD request to the server. + * httpInitialize() - Initialize the HTTP interface library and set + * the default HTTP proxy (if any). + * httpOptions() - Send an OPTIONS request to the server. + * _httpPeek() - Peek at data from a HTTP connection. + * httpPost() - Send a POST request to the server. + * httpPrintf() - Print a formatted string to a HTTP connection. + * httpPut() - Send a PUT request to the server. + * httpRead() - Read data from a HTTP connection. + * httpRead2() - Read data from a HTTP connection. + * _httpReadCDSA() - Read function for the CDSA library. + * _httpReadGNUTLS() - Read function for the GNU TLS library. + * httpReconnect() - Reconnect to a HTTP server. + * httpSetAuthString() - Set the current authorization string. + * httpSetCredentials() - Set the credentials associated with an + * encrypted connection. + * httpSetCookie() - Set the cookie value(s). + * httpSetExpect() - Set the Expect: header in a request. + * httpSetField() - Set the value of an HTTP header. + * httpSetLength() - Set the content-length and content-encoding. + * httpSetTimeout() - Set read/write timeouts and an optional + * callback. + * httpTrace() - Send an TRACE request to the server. + * _httpUpdate() - Update the current HTTP status for incoming + * data. + * httpUpdate() - Update the current HTTP state for incoming + * data. + * _httpWait() - Wait for data available on a connection (no + * flush). + * httpWait() - Wait for data available on a connection. + * httpWrite() - Write data to a HTTP connection. + * httpWrite2() - Write data to a HTTP connection. + * _httpWriteCDSA() - Write function for the CDSA library. + * _httpWriteGNUTLS() - Write function for the GNU TLS library. + * http_bio_ctrl() - Control the HTTP connection. + * http_bio_free() - Free OpenSSL data. + * http_bio_new() - Initialize an OpenSSL BIO structure. + * http_bio_puts() - Send a string for OpenSSL. + * http_bio_read() - Read data for OpenSSL. + * http_bio_write() - Write data for OpenSSL. + * http_debug_hex() - Do a hex dump of a buffer. + * http_field() - Return the field index for a field name. + * http_read_ssl() - Read from a SSL/TLS connection. + * http_send() - Send a request with all fields and the trailing + * blank line. + * http_set_credentials() - Set the SSL/TLS credentials. + * http_set_timeout() - Set the socket timeout values. + * http_set_wait() - Set the default wait value for reads. + * http_setup_ssl() - Set up SSL/TLS support on a connection. + * http_shutdown_ssl() - Shut down SSL/TLS on a connection. + * http_upgrade() - Force upgrade to TLS encryption. + * http_write() - Write a buffer to a HTTP connection. + * http_write_chunk() - Write a chunked buffer. + * http_write_ssl() - Write to a SSL/TLS connection. */ /* @@ -1116,167 +1116,6 @@ httpGetLength2(http_t *http) /* I - Connection to server */ } -/* - * 'httpGetStatus()' - Get the status of the last HTTP request. - * - * @since CUPS 1.2/Mac OS X 10.5@ - */ - -http_status_t /* O - HTTP status */ -httpGetStatus(http_t *http) /* I - Connection to server */ -{ - return (http ? http->status : HTTP_ERROR); -} - - -/* - * 'httpGetSubField()' - Get a sub-field value. - * - * @deprecated@ - */ - -char * /* O - Value or NULL */ -httpGetSubField(http_t *http, /* I - Connection to server */ - http_field_t field, /* I - Field index */ - const char *name, /* I - Name of sub-field */ - char *value) /* O - Value string */ -{ - return (httpGetSubField2(http, field, name, value, HTTP_MAX_VALUE)); -} - - -/* - * 'httpGetSubField2()' - Get a sub-field value. - * - * @since CUPS 1.2/Mac OS X 10.5@ - */ - -char * /* O - Value or NULL */ -httpGetSubField2(http_t *http, /* I - Connection to server */ - http_field_t field, /* I - Field index */ - const char *name, /* I - Name of sub-field */ - char *value, /* O - Value string */ - int valuelen) /* I - Size of value buffer */ -{ - const char *fptr; /* Pointer into field */ - char temp[HTTP_MAX_VALUE], /* Temporary buffer for name */ - *ptr, /* Pointer into string buffer */ - *end; /* End of value buffer */ - - DEBUG_printf(("2httpGetSubField2(http=%p, field=%d, name=\"%s\", value=%p, " - "valuelen=%d)", http, field, name, value, valuelen)); - - if (!http || !name || !value || valuelen < 2 || - field <= HTTP_FIELD_UNKNOWN || field >= HTTP_FIELD_MAX) - return (NULL); - - end = value + valuelen - 1; - - for (fptr = http->fields[field]; *fptr;) - { - /* - * Skip leading whitespace... - */ - - while (_cups_isspace(*fptr)) - fptr ++; - - if (*fptr == ',') - { - fptr ++; - continue; - } - - /* - * Get the sub-field name... - */ - - for (ptr = temp; - *fptr && *fptr != '=' && !_cups_isspace(*fptr) && - ptr < (temp + sizeof(temp) - 1); - *ptr++ = *fptr++); - - *ptr = '\0'; - - DEBUG_printf(("4httpGetSubField2: name=\"%s\"", temp)); - - /* - * Skip trailing chars up to the '='... - */ - - while (_cups_isspace(*fptr)) - fptr ++; - - if (!*fptr) - break; - - if (*fptr != '=') - continue; - - /* - * Skip = and leading whitespace... - */ - - fptr ++; - - while (_cups_isspace(*fptr)) - fptr ++; - - if (*fptr == '\"') - { - /* - * Read quoted string... - */ - - for (ptr = value, fptr ++; - *fptr && *fptr != '\"' && ptr < end; - *ptr++ = *fptr++); - - *ptr = '\0'; - - while (*fptr && *fptr != '\"') - fptr ++; - - if (*fptr) - fptr ++; - } - else - { - /* - * Read unquoted string... - */ - - for (ptr = value; - *fptr && !_cups_isspace(*fptr) && *fptr != ',' && ptr < end; - *ptr++ = *fptr++); - - *ptr = '\0'; - - while (*fptr && !_cups_isspace(*fptr) && *fptr != ',') - fptr ++; - } - - DEBUG_printf(("4httpGetSubField2: value=\"%s\"", value)); - - /* - * See if this is the one... - */ - - if (!strcmp(name, temp)) - { - DEBUG_printf(("3httpGetSubField2: Returning \"%s\"", value)); - return (value); - } - } - - value[0] = '\0'; - - DEBUG_puts("3httpGetSubField2: Returning NULL"); - - return (NULL); -} - - /* * 'httpGets()' - Get a line of text from a HTTP connection. */ @@ -1457,6 +1296,189 @@ httpGets(char *line, /* I - Line to read into */ } +/* + * 'httpGetState()' - Get the current state of the HTTP request. + */ + +http_state_t /* O - HTTP state */ +httpGetState(http_t *http) /* I - Connection to server */ +{ + return (http ? http->state : HTTP_ERROR); +} + + +/* + * 'httpGetStatus()' - Get the status of the last HTTP request. + * + * @since CUPS 1.2/Mac OS X 10.5@ + */ + +http_status_t /* O - HTTP status */ +httpGetStatus(http_t *http) /* I - Connection to server */ +{ + return (http ? http->status : HTTP_ERROR); +} + + +/* + * 'httpGetSubField()' - Get a sub-field value. + * + * @deprecated@ + */ + +char * /* O - Value or NULL */ +httpGetSubField(http_t *http, /* I - Connection to server */ + http_field_t field, /* I - Field index */ + const char *name, /* I - Name of sub-field */ + char *value) /* O - Value string */ +{ + return (httpGetSubField2(http, field, name, value, HTTP_MAX_VALUE)); +} + + +/* + * 'httpGetSubField2()' - Get a sub-field value. + * + * @since CUPS 1.2/Mac OS X 10.5@ + */ + +char * /* O - Value or NULL */ +httpGetSubField2(http_t *http, /* I - Connection to server */ + http_field_t field, /* I - Field index */ + const char *name, /* I - Name of sub-field */ + char *value, /* O - Value string */ + int valuelen) /* I - Size of value buffer */ +{ + const char *fptr; /* Pointer into field */ + char temp[HTTP_MAX_VALUE], /* Temporary buffer for name */ + *ptr, /* Pointer into string buffer */ + *end; /* End of value buffer */ + + DEBUG_printf(("2httpGetSubField2(http=%p, field=%d, name=\"%s\", value=%p, " + "valuelen=%d)", http, field, name, value, valuelen)); + + if (!http || !name || !value || valuelen < 2 || + field <= HTTP_FIELD_UNKNOWN || field >= HTTP_FIELD_MAX) + return (NULL); + + end = value + valuelen - 1; + + for (fptr = http->fields[field]; *fptr;) + { + /* + * Skip leading whitespace... + */ + + while (_cups_isspace(*fptr)) + fptr ++; + + if (*fptr == ',') + { + fptr ++; + continue; + } + + /* + * Get the sub-field name... + */ + + for (ptr = temp; + *fptr && *fptr != '=' && !_cups_isspace(*fptr) && + ptr < (temp + sizeof(temp) - 1); + *ptr++ = *fptr++); + + *ptr = '\0'; + + DEBUG_printf(("4httpGetSubField2: name=\"%s\"", temp)); + + /* + * Skip trailing chars up to the '='... + */ + + while (_cups_isspace(*fptr)) + fptr ++; + + if (!*fptr) + break; + + if (*fptr != '=') + continue; + + /* + * Skip = and leading whitespace... + */ + + fptr ++; + + while (_cups_isspace(*fptr)) + fptr ++; + + if (*fptr == '\"') + { + /* + * Read quoted string... + */ + + for (ptr = value, fptr ++; + *fptr && *fptr != '\"' && ptr < end; + *ptr++ = *fptr++); + + *ptr = '\0'; + + while (*fptr && *fptr != '\"') + fptr ++; + + if (*fptr) + fptr ++; + } + else + { + /* + * Read unquoted string... + */ + + for (ptr = value; + *fptr && !_cups_isspace(*fptr) && *fptr != ',' && ptr < end; + *ptr++ = *fptr++); + + *ptr = '\0'; + + while (*fptr && !_cups_isspace(*fptr) && *fptr != ',') + fptr ++; + } + + DEBUG_printf(("4httpGetSubField2: value=\"%s\"", value)); + + /* + * See if this is the one... + */ + + if (!strcmp(name, temp)) + { + DEBUG_printf(("3httpGetSubField2: Returning \"%s\"", value)); + return (value); + } + } + + value[0] = '\0'; + + DEBUG_puts("3httpGetSubField2: Returning NULL"); + + return (NULL); +} + + +/* + * 'httpGetVersion()' - Get the HTTP version at the other end. + */ + +http_version_t /* O - Version number */ +httpGetVersion(http_t *http) /* I - Connection to server */ +{ + return (http ? http->version : HTTP_1_0); +} + + /* * 'httpHead()' - Send a HEAD request to the server. */ @@ -3199,10 +3221,13 @@ _httpWriteGNUTLS( DEBUG_printf(("6_httpWriteGNUTLS(ptr=%p, data=%p, length=%d)", ptr, data, (int)length)); +#ifdef DEBUG http_debug_hex("_httpWriteGNUTLS", data, (int)length); +#endif /* DEBUG */ bytes = send(((http_t *)ptr)->fd, data, length, 0); DEBUG_printf(("_httpWriteGNUTLS: bytes=%d", (int)bytes)); + return (bytes); } #endif /* HAVE_SSL && HAVE_GNUTLS */ diff --git a/cups/http.h b/cups/http.h index 5e3a42d3a..a70e85cf5 100644 --- a/cups/http.h +++ b/cups/http.h @@ -459,7 +459,12 @@ extern void httpFreeCredentials(cups_array_t *certs) _CUPS_API_1_5; extern int httpSetCredentials(http_t *http, cups_array_t *certs) _CUPS_API_1_5; extern void httpSetTimeout(http_t *http, double timeout, - http_timeout_cb_t cb, void *user_data); + http_timeout_cb_t cb, void *user_data) + _CUPS_API_1_5; + +/**** New in CUPS 1.6 ****/ +extern http_state_t httpGetState(http_t *http) _CUPS_API_1_6; +extern http_version_t httpGetVersion(http_t *http) _CUPS_API_1_6; /* diff --git a/cups/ipp-private.h b/cups/ipp-private.h index 2120c0865..1fcea0f4e 100644 --- a/cups/ipp-private.h +++ b/cups/ipp-private.h @@ -3,7 +3,7 @@ * * Private IPP definitions for CUPS. * - * Copyright 2007-2010 by Apple Inc. + * Copyright 2007-2011 by Apple Inc. * Copyright 1997-2006 by Easy Software Products. * * These coded instructions, statements, and computer programs are the @@ -46,6 +46,103 @@ extern "C" { * Structures... */ +typedef union _ipp_request_u /**** Request Header ****/ +{ + struct /* Any Header */ + { + ipp_uchar_t version[2]; /* Protocol version number */ + int op_status; /* Operation ID or status code*/ + int request_id; /* Request ID */ + } any; + + struct /* Operation Header */ + { + ipp_uchar_t version[2]; /* Protocol version number */ + ipp_op_t operation_id; /* Operation ID */ + int request_id; /* Request ID */ + } op; + + struct /* Status Header */ + { + ipp_uchar_t version[2]; /* Protocol version number */ + ipp_status_t status_code; /* Status code */ + int request_id; /* Request ID */ + } status; + + /**** New in CUPS 1.1.19 ****/ + struct /* Event Header @since CUPS 1.1.19/Mac OS X 10.3@ */ + { + ipp_uchar_t version[2]; /* Protocol version number */ + ipp_status_t status_code; /* Status code */ + int request_id; /* Request ID */ + } event; +} _ipp_request_t; + +/**** New in CUPS 1.1.19 ****/ + +typedef union _ipp_value_u /**** Attribute Value ****/ +{ + int integer; /* Integer/enumerated value */ + + char boolean; /* Boolean value */ + + ipp_uchar_t date[11]; /* Date/time value */ + + struct + { + int xres, /* Horizontal resolution */ + yres; /* Vertical resolution */ + ipp_res_t units; /* Resolution units */ + } resolution; /* Resolution value */ + + struct + { + int lower, /* Lower value */ + upper; /* Upper value */ + } range; /* Range of integers value */ + + struct + { + char *language; /* Language code */ + char *text; /* String */ + } string; /* String with language value */ + + struct + { + int length; /* Length of attribute */ + void *data; /* Data in attribute */ + } unknown; /* Unknown attribute type */ + +/**** New in CUPS 1.1.19 ****/ + ipp_t *collection; /* Collection value @since CUPS 1.1.19/Mac OS X 10.3@ */ +} _ipp_value_t; + +struct _ipp_attribute_s /**** Attribute ****/ +{ + ipp_attribute_t *next; /* Next attribute in list */ + ipp_tag_t group_tag, /* Job/Printer/Operation group tag */ + value_tag; /* What type of value is it? */ + char *name; /* Name of attribute */ + int num_values; /* Number of values */ + _ipp_value_t values[1]; /* Values */ +}; + +struct _ipp_s /**** IPP Request/Response/Notification ****/ +{ + ipp_state_t state; /* State of request */ + _ipp_request_t request; /* Request header */ + ipp_attribute_t *attrs; /* Attributes */ + ipp_attribute_t *last; /* Last attribute in list */ + ipp_attribute_t *current; /* Current attribute (for read/write) */ + ipp_tag_t curtag; /* Current attribute group tag */ + +/**** New in CUPS 1.2 ****/ + ipp_attribute_t *prev; /* Previous attribute (for read) @since CUPS 1.2/Mac OS X 10.5@ */ + +/**** New in CUPS 1.4.4 ****/ + int use; /* Use count @since CUPS 1.4.4/Mac OS X 10.6.?@ */ +}; + typedef struct _ipp_buffer_s /**** Read/write buffer ****/ { unsigned char d[IPP_BUF_SIZE];/* Data buffer */ @@ -66,11 +163,7 @@ typedef struct /**** Attribute mapping data ****/ * Prototypes for private functions... */ -extern ipp_attribute_t *_ippAddAttr(ipp_t *ipp, int num_values); -extern size_t _ippAttrString(ipp_attribute_t *attr, char *buffer, - size_t bufsize); extern _ipp_option_t *_ippFindOption(const char *name); -extern void _ippFreeAttr(ipp_attribute_t *attr); /* diff --git a/cups/ipp-support.c b/cups/ipp-support.c index b22b4727b..030eece1e 100644 --- a/cups/ipp-support.c +++ b/cups/ipp-support.c @@ -16,16 +16,19 @@ * * Contents: * - * _ippAttrString() - Convert the attribute's value to a string. - * ippErrorString() - Return a name for the given status code. - * ippErrorValue() - Return a status code for the given name. - * ippOpString() - Return a name for the given operation id. - * ippOpValue() - Return an operation id for the given name. - * ippPort() - Return the default IPP port number. - * ippSetPort() - Set the default port number. - * ippTagString() - Return the tag name corresponding to a tag value. - * ippTagValue() - Return the tag value corresponding to a tag name. - * ipp_col_string() - Convert a collection to a string. + * ippAttributeString() - Convert the attribute's value to a string. + * ippEnumString() - Return a string corresponding to the enum value. + * ippEnumValue() - Return the value associated with a given enum + * string. + * ippErrorString() - Return a name for the given status code. + * ippErrorValue() - Return a status code for the given name. + * ippOpString() - Return a name for the given operation id. + * ippOpValue() - Return an operation id for the given name. + * ippPort() - Return the default IPP port number. + * ippSetPort() - Set the default port number. + * ippTagString() - Return the tag name corresponding to a tag value. + * ippTagValue() - Return the tag value corresponding to a tag name. + * ipp_col_string() - Convert a collection to a string. */ /* @@ -40,18 +43,18 @@ */ static const char * const ipp_status_oks[] = /* "OK" status codes */ - { + { /* (name) = abandoned standard value */ "successful-ok", "successful-ok-ignored-or-substituted-attributes", "successful-ok-conflicting-attributes", "successful-ok-ignored-subscriptions", - "successful-ok-ignored-notifications", + "(successful-ok-ignored-notifications)", "successful-ok-too-many-events", - "successful-ok-but-cancel-subscription", + "(successful-ok-but-cancel-subscription)", "successful-ok-events-complete" }, * const ipp_status_400s[] = /* Client errors */ - { + { /* (name) = abandoned standard value */ "client-error-bad-request", "client-error-forbidden", "client-error-not-authenticated", @@ -74,8 +77,8 @@ static const char * const ipp_status_oks[] = /* "OK" status codes */ "client-error-attributes-not-settable", "client-error-ignored-all-subscriptions", "client-error-too-many-subscriptions", - "client-error-ignored-all-notifications", - "client-error-print-support-file-not-found" + "(client-error-ignored-all-notifications)", + "(client-error-client-print-support-file-not-found)" }, * const ipp_status_500s[] = /* Server errors */ { @@ -89,7 +92,9 @@ static const char * const ipp_status_oks[] = /* "OK" status codes */ "server-error-busy", "server-error-job-canceled", "server-error-multiple-document-jobs-not-supported", - "server-error-printer-is-deactivated" + "server-error-printer-is-deactivated", + "server-error-too-many-jobs", + "server-error-too-many-documents" }, * const ipp_status_1000s[] = /* CUPS internal */ { @@ -97,7 +102,7 @@ static const char * const ipp_status_oks[] = /* "OK" status codes */ "cups-pki-error", "cups-upgrade-required" }; -static char * const ipp_std_ops[] = +static const char * const ipp_std_ops[] = { /* 0x0000 - 0x000f */ "0x00", @@ -131,13 +136,13 @@ static char * const ipp_std_ops[] = "Renew-Subscription", "Cancel-Subscription", "Get-Notifications", - "Send-Notifications", - "0x1e", - "0x1f", + "(Send-Notifications)", + "(Get-Resource-Attributes)", + "(Get-Resource-Data)", /* 0x0020 - 0x002f */ - "0x20", - "Get-Printer-Support-Files", + "(Get-Resources)", + "(Get-Printer-Support-Files)", "Enable-Printer", "Disable-Printer", "Pause-Printer-After-Current-Job", @@ -206,7 +211,8 @@ static char * const ipp_std_ops[] = /* 0x06 */ "event-notification-attributes-tag", /* 0x07 */ - "0x08", /* 0x08 */ + "(resource-attributes-tag)", + /* 0x08 */ "document-attributes-tag", /* 0x09 */ "0x0a", /* 0x0a */ @@ -275,22 +281,115 @@ static char * const ipp_std_ops[] = "mimeMediaType", /* 0x49 */ "memberAttrName" /* 0x4a */ }; -static const char * const job_states[] = -{ /* job-state enums */ - "pending", - "pending-held", - "processing", - "processing-stopped", - "canceled", - "aborted", - "completed" -}; -static const char * const printer_states[] = -{ /* printer-state enums */ - "idle", - "processing", - "stopped", -}; +static const char * const ipp_document_states[] = + { /* document-state-enums */ + "pending", + "4", + "processing", + "6", + "canceled", + "aborted", + "completed" + }, + * const ipp_finishings[] = + { /* finishings enums */ + "none", + "staple", + "punch", + "cover", + "bind", + "saddle-stitch", + "edge-stitch", + "fold", + "trim", + "bale", + "booklet-maker", + "jog-offset", + "15", + "16", + "17", + "18", + "19", + "staple-top-left", + "staple-bottom-left", + "staple-top-right", + "staple-bottom-right", + "edge-stitch-left", + "edge-stitch-top", + "edge-stitch-right", + "edge-stitch-bottom", + "staple-dual-left", + "staple-dual-top", + "staple-dual-right", + "staple-dual-bottom", + "32", + "33", + "34", + "35", + "36", + "37", + "38", + "39", + "40", + "41", + "42", + "43", + "44", + "45", + "46", + "47", + "48", + "49", + "bind-left", + "bind-top", + "bind-right", + "bind-bottom", + "54", + "55", + "56", + "57", + "58", + "59", + "trim-after-pages", + "trim-after-documents", + "trim-after-copies", + "trim-after-job" + }, + * const ipp_job_collation_types[] = + { /* job-collation-type enums */ + "uncollated-sheets", + "collated-documents", + "uncollated-documents" + }, + * const ipp_job_states[] = + { /* job-state enums */ + "pending", + "pending-held", + "processing", + "processing-stopped", + "canceled", + "aborted", + "completed" + }, + * const ipp_orientation_requesteds[] = + { /* orientation-requested enums */ + "portrait", + "landscape", + "reverse-landscape", + "reverse-portrait" + }, + * const ipp_print_qualities[] = + { /* print-quality enums */ + "draft", + "normal", + "high" + }, + * const ipp_printer_states[] = + { /* printer-state enums */ + "idle", + "processing", + "stopped", + }; /* @@ -301,24 +400,27 @@ static size_t ipp_col_string(ipp_t *col, char *buffer, size_t bufsize); /* - * '_ippAttrString()' - Convert the attribute's value to a string. + * 'ippAttributeString()' - Convert the attribute's value to a string. * * Returns the number of bytes that would be written, not including the * trailing nul. The buffer pointer can be NULL to get the required length, * just like (v)snprintf. + * + * @since CUPS 1.6@ */ size_t /* O - Number of bytes less nul */ -_ippAttrString(ipp_attribute_t *attr, /* I - Attribute */ - char *buffer, /* I - String buffer or NULL */ - size_t bufsize) /* I - Size of string buffer */ +ippAttributeString( + ipp_attribute_t *attr, /* I - Attribute */ + char *buffer, /* I - String buffer or NULL */ + size_t bufsize) /* I - Size of string buffer */ { int i; /* Looping var */ char *bufptr, /* Pointer into buffer */ *bufend, /* End of buffer */ temp[256]; /* Temporary string */ const char *ptr; /* Pointer into string */ - ipp_value_t *val; /* Current value */ + _ipp_value_t *val; /* Current value */ if (!attr || !attr->name) @@ -348,40 +450,13 @@ _ippAttrString(ipp_attribute_t *attr, /* I - Attribute */ switch (attr->value_tag & ~IPP_TAG_COPY) { case IPP_TAG_ENUM : - if (!strcmp(attr->name, "printer-state") && - val->integer >= IPP_PRINTER_IDLE && - val->integer <= IPP_PRINTER_STOPPED) - { - ptr = printer_states[val->integer - IPP_PRINTER_IDLE]; + ptr = ippEnumString(attr->name, val->integer); - if (buffer && bufptr < bufend) - strlcpy(bufptr, ptr, bufend - bufptr + 1); - - bufptr += strlen(ptr); - break; - } - else if (!strcmp(attr->name, "job-state") && - val->integer >= IPP_JOB_PENDING && - val->integer <= IPP_JOB_COMPLETED) - { - ptr = job_states[val->integer - IPP_JOB_PENDING]; - - if (buffer && bufptr < bufend) - strlcpy(bufptr, ptr, bufend - bufptr + 1); - - bufptr += strlen(ptr); - break; - } - else if (!strcmp(attr->name, "operations-supported")) - { - ptr = ippOpString(val->integer); - - if (buffer && bufptr < bufend) - strlcpy(bufptr, ptr, bufend - bufptr + 1); + if (buffer && bufptr < bufend) + strlcpy(bufptr, ptr, bufend - bufptr + 1); - bufptr += strlen(ptr); - break; - } + bufptr += strlen(ptr); + break; case IPP_TAG_INTEGER : if (buffer && bufptr < bufend) @@ -459,7 +534,7 @@ _ippAttrString(ipp_attribute_t *attr, /* I - Attribute */ for (ptr = val->string.text; *ptr; ptr ++) { - if (*ptr == '\\' || *ptr == '\"') + if (*ptr == '\\' || *ptr == '\"' || *ptr == '[') { if (buffer && bufptr < bufend) *bufptr = '\\'; @@ -470,6 +545,25 @@ _ippAttrString(ipp_attribute_t *attr, /* I - Attribute */ *bufptr = *ptr; bufptr ++; } + + if (val->string.language) + { + /* + * Add "[language]" to end of string... + */ + + if (buffer && bufptr < bufend) + *bufptr = '['; + bufptr ++; + + if (buffer && bufptr < bufend) + strlcpy(bufptr, val->string.language, bufend - bufptr); + bufptr += strlen(val->string.language); + + if (buffer && bufptr < bufend) + *bufptr = ']'; + bufptr ++; + } break; case IPP_TAG_BEGIN_COLLECTION : @@ -529,6 +623,159 @@ _ippAttrString(ipp_attribute_t *attr, /* I - Attribute */ } +/* + * 'ippEnumString()' - Return a string corresponding to the enum value. + */ + +const char * /* O - Enum string */ +ippEnumString(const char *attrname, /* I - Attribute name */ + int enumvalue) /* I - Enum value */ +{ + _cups_globals_t *cg = _cupsGlobals(); /* Pointer to library globals */ + + + /* + * Check for standard enum values... + */ + + if (!strcmp(attrname, "document-state") && + enumvalue >= 3 && + enumvalue <= (3 + (int)(sizeof(ipp_document_states) / + sizeof(ipp_document_states[0])))) + return (ipp_document_states[enumvalue - 3]); + else if ((!strcmp(attrname, "finishings") || + !strcmp(attrname, "finishings-actual") || + !strcmp(attrname, "finishings-default") || + !strcmp(attrname, "finishings-ready") || + !strcmp(attrname, "finishings-supported")) && + enumvalue >= 3 && + enumvalue <= (3 + (int)(sizeof(ipp_finishings) / sizeof(ipp_finishings[0])))) + return (ipp_finishings[enumvalue - 3]); + else if ((!strcmp(attrname, "job-collation-type") || + !strcmp(attrname, "job-collation-type-actual")) && + enumvalue >= 3 && + enumvalue <= (3 + (int)(sizeof(ipp_job_collation_types) / + sizeof(ipp_job_collation_types[0])))) + return (ipp_job_collation_types[enumvalue - 3]); + else if (!strcmp(attrname, "job-state") && + enumvalue >= IPP_JOB_PENDING && enumvalue <= IPP_JOB_COMPLETED) + return (ipp_job_states[enumvalue - IPP_JOB_PENDING]); + else if (!strcmp(attrname, "operations-supported")) + return (ippOpString((ipp_op_t)enumvalue)); + else if ((!strcmp(attrname, "orientation-requested") || + !strcmp(attrname, "orientation-requested-actual") || + !strcmp(attrname, "orientation-requested-default") || + !strcmp(attrname, "orientation-requested-supported")) && + enumvalue >= 3 && + enumvalue <= (3 + (int)(sizeof(ipp_orientation_requesteds) / + sizeof(ipp_orientation_requesteds[0])))) + return (ipp_orientation_requesteds[enumvalue - 3]); + else if ((!strcmp(attrname, "print-quality") || + !strcmp(attrname, "print-quality-actual") || + !strcmp(attrname, "print-quality-default") || + !strcmp(attrname, "print-quality-supported")) && + enumvalue >= 3 && + enumvalue <= (3 + (int)(sizeof(ipp_print_qualities) / + sizeof(ipp_print_qualities[0])))) + return (ipp_print_qualities[enumvalue - 3]); + else if (!strcmp(attrname, "printer-state") && + enumvalue >= IPP_PRINTER_IDLE && enumvalue <= IPP_PRINTER_STOPPED) + return (ipp_printer_states[enumvalue - IPP_PRINTER_IDLE]); + + /* + * Not a standard enum value, just return the decimal equivalent... + */ + + snprintf(cg->ipp_unknown, sizeof(cg->ipp_unknown), "%d", enumvalue); + return (cg->ipp_unknown); +} + + +/* + * 'ippEnumValue()' - Return the value associated with a given enum string. + */ + +int /* O - Enum value or -1 if unknown */ +ippEnumValue(const char *attrname, /* I - Attribute name */ + const char *enumstring) /* I - Enum string */ +{ + int i, /* Looping var */ + num_strings; /* Number of strings to compare */ + const char * const *strings; /* Strings to compare */ + + + /* + * If the string is just a number, return it... + */ + + if (isdigit(*enumstring & 255)) + return (strtol(enumstring, NULL, 0)); + + /* + * Otherwise look up the string... + */ + + if (!strcmp(attrname, "document-state")) + { + num_strings = (int)(sizeof(ipp_document_states) / sizeof(ipp_document_states[0])); + strings = ipp_document_states; + } + else if (!strcmp(attrname, "finishings") || + !strcmp(attrname, "finishings-actual") || + !strcmp(attrname, "finishings-default") || + !strcmp(attrname, "finishings-ready") || + !strcmp(attrname, "finishings-supported")) + { + num_strings = (int)(sizeof(ipp_finishings) / sizeof(ipp_finishings[0])); + strings = ipp_finishings; + } + else if (!strcmp(attrname, "job-collation-type") || + !strcmp(attrname, "job-collation-type-actual")) + { + num_strings = (int)(sizeof(ipp_job_collation_types) / + sizeof(ipp_job_collation_types[0])); + strings = ipp_job_collation_types; + } + else if (!strcmp(attrname, "job-state")) + { + num_strings = (int)(sizeof(ipp_job_states) / sizeof(ipp_job_states[0])); + strings = ipp_job_states; + } + else if (!strcmp(attrname, "operations-supported")) + return (ippOpValue(enumstring)); + else if (!strcmp(attrname, "orientation-requested") || + !strcmp(attrname, "orientation-requested-actual") || + !strcmp(attrname, "orientation-requested-default") || + !strcmp(attrname, "orientation-requested-supported")) + { + num_strings = (int)(sizeof(ipp_orientation_requesteds) / + sizeof(ipp_orientation_requesteds[0])); + strings = ipp_orientation_requesteds; + } + else if (!strcmp(attrname, "print-quality") || + !strcmp(attrname, "print-quality-actual") || + !strcmp(attrname, "print-quality-default") || + !strcmp(attrname, "print-quality-supported")) + { + num_strings = (int)(sizeof(ipp_print_qualities) / sizeof(ipp_print_qualities[0])); + strings = ipp_print_qualities; + } + else if (!strcmp(attrname, "printer-state")) + { + num_strings = (int)(sizeof(ipp_printer_states) / sizeof(ipp_printer_states[0])); + strings = ipp_printer_states; + } + else + return (-1); + + for (i = 0; i < num_strings; i ++) + if (!strcmp(enumstring, strings[i])) + return (i + 3); + + return (-1); +} + + /* * 'ippErrorString()' - Return a name for the given status code. */ @@ -811,9 +1058,9 @@ ipp_col_string(ipp_t *col, /* I - Collection attribute */ bufptr += strlen(attr->name) + 1; if (buffer && bufptr < bufend) - bufptr += _ippAttrString(attr, bufptr, bufend - bufptr + 1); + bufptr += ippAttributeString(attr, bufptr, bufend - bufptr + 1); else - bufptr += _ippAttrString(attr, temp, sizeof(temp)); + bufptr += ippAttributeString(attr, temp, sizeof(temp)); } if (buffer && bufptr < bufend) diff --git a/cups/ipp.c b/cups/ipp.c index d752c35c0..0e22b49ff 100644 --- a/cups/ipp.c +++ b/cups/ipp.c @@ -1,5 +1,5 @@ /* - * "$Id: ipp.c 7847 2008-08-19 04:22:14Z mike $" + * "$Id: ipp.c 10102 2011-11-02 23:52:39Z mike $" * * Internet Printing Protocol functions for CUPS. * @@ -16,44 +16,90 @@ * * Contents: * - * ippAddBoolean() - Add a boolean attribute to an IPP message. - * ippAddBooleans() - Add an array of boolean values. - * ippAddDate() - Add a date attribute to an IPP message. - * ippAddInteger() - Add a integer attribute to an IPP message. - * ippAddIntegers() - Add an array of integer values. + * ippAddBoolean() - Add a boolean attribute to an IPP message. + * ippAddBooleans() - Add an array of boolean values. + * ippAddCollection() - Add a collection value. + * ippAddCollections() - Add an array of collection values. + * ippAddDate() - Add a date attribute to an IPP message. + * ippAddInteger() - Add a integer attribute to an IPP message. + * ippAddIntegers() - Add an array of integer values. * ippAddOctetString() - Add an octetString value to an IPP message. - * ippAddString() - Add a language-encoded string to an IPP message. - * ippAddStrings() - Add language-encoded strings to an IPP message. - * ippAddRange() - Add a range of values to an IPP message. - * ippAddRanges() - Add ranges of values to an IPP message. + * ippAddOutOfBand() - Add an out-of-band value to an IPP message. + * ippAddRange() - Add a range of values to an IPP message. + * ippAddRanges() - Add ranges of values to an IPP message. * ippAddResolution() - Add a resolution value to an IPP message. * ippAddResolutions() - Add resolution values to an IPP message. - * ippAddSeparator() - Add a group separator to an IPP message. - * ippDateToTime() - Convert from RFC 1903 Date/Time format to - * UNIX time in seconds. - * ippDelete() - Delete an IPP message. + * ippAddSeparator() - Add a group separator to an IPP message. + * ippAddString() - Add a language-encoded string to an IPP message. + * ippAddStrings() - Add language-encoded strings to an IPP message. + * ippCopyAttribute() - Copy an attribute. + * ippCopyAttributes() - Copy attributes from one IPP message to another. + * ippDateToTime() - Convert from RFC 1903 Date/Time format to UNIX + * time in seconds. + * ippDelete() - Delete an IPP message. * ippDeleteAttribute() - Delete a single attribute in an IPP message. + * ippDeleteValues() - Delete values in an attribute. * ippFindAttribute() - Find a named attribute in a request... * ippFindNextAttribute() - Find the next named attribute in a request... - * ippLength() - Compute the length of an IPP message. - * ippNew() - Allocate a new IPP message. - * ippNewRequest() - Allocate a new IPP message. - * ippRead() - Read data for an IPP message from a HTTP - * connection. - * ippReadFile() - Read data for an IPP message from a file. - * ippReadIO() - Read data for an IPP message. - * ippTimeToDate() - Convert from UNIX time to RFC 1903 format. - * ippWrite() - Write data for an IPP message to a HTTP - * connection. - * ippWriteFile() - Write data for an IPP message to a file. - * ippWriteIO() - Write data for an IPP message. - * _ippAddAttr() - Add a new attribute to the request. - * _ippFreeAttr() - Free an attribute. - * ipp_length() - Compute the length of an IPP message or - * collection value. - * ipp_read_http() - Semi-blocking read on a HTTP connection... - * ipp_read_file() - Read IPP data from a file. - * ipp_write_file() - Write IPP data to a file. + * ippFirstAttribute() - Return the first attribute in the message. + * ippGetBoolean() - Get a boolean value for an attribute. + * ippGetCollection() - Get a collection value for an attribute. + * ippGetCount() - Get the number of values in an attribute. + * ippGetGroupTag() - Get the group associated with an attribute. + * ippGetInteger() - Get the integer/enum value for an attribute. + * ippGetName() - Get the attribute name. + * ippGetOperation() - Get the operation ID in an IPP message. + * ippGetRequestId() - Get the request ID from an IPP message. + * ippGetResolution() - Get a resolution value for an attribute. + * ippGetStatusCode() - Get the status code from an IPP response or event + * message. + * ippGetString() - Get the string and optionally the language code + * for an attribute. + * ippGetValueTag() - Get the value tag for an attribute. + * ippGetVersion() - Get the major and minor version number from an + * IPP message. + * ippLength() - Compute the length of an IPP message. + * ippNextAttribute() - Return the next attribute in the message. + * ippNew() - Allocate a new IPP message. + * ippNewRequest() - Allocate a new IPP request message. + * ippRead() - Read data for an IPP message from a HTTP + * connection. + * ippReadFile() - Read data for an IPP message from a file. + * ippReadIO() - Read data for an IPP message. + * ippSetBoolean() - Set a boolean value in an attribute. + * ippSetCollection() - Set a collection value in an attribute. + * ippSetGroupTag() - Set the group tag of an attribute. + * ippSetInteger() - Set an integer or enum value in an attribute. + * ippSetName() - Set the name of an attribute. + * ippSetOperation() - Set the operation ID in an IPP request message. + * ippSetRange() - Set a rangeOfInteger value in an attribute. + * ippSetRequestId() - Set the request ID in an IPP message. + * ippSetResolution() - Set a resolution value in an attribute. + * ippSetStatusCode() - Set the status code in an IPP response or event + * message. + * ippSetString() - Set a string value in an attribute. + * ippSetValueTag() - Set the value tag of an attribute. + * ippSetVersion() - Set the version number in an IPP message. + * ippTimeToDate() - Convert from UNIX time to RFC 1903 format. + * ippWrite() - Write data for an IPP message to a HTTP + * connection. + * ippWriteFile() - Write data for an IPP message to a file. + * ippWriteIO() - Write data for an IPP message. + * ipp_add_attr() - Add a new attribute to the message. + * ipp_buffer_get() - Get a read/write buffer. + * ipp_buffer_release() - Release a read/write buffer. + * ipp_free_values() - Free attribute values. + * ipp_get_code() - Convert a C locale/charset name into an IPP + * language/charset code. + * ipp_lang_code() - Convert a C locale name into an IPP language + * code. + * ipp_length() - Compute the length of an IPP message or + * collection value. + * ipp_read_http() - Semi-blocking read on a HTTP connection... + * ipp_read_file() - Read IPP data from a file. + * ipp_set_value() - Get the value element from an attribute, + * expanding it as needed. + * ipp_write_file() - Write IPP data to a file. */ /* @@ -70,19 +116,34 @@ * Local functions... */ +static ipp_attribute_t *ipp_add_attr(ipp_t *ipp, const char *name, ipp_tag_t group_tag, + ipp_tag_t value_tag, int num_values); static unsigned char *ipp_buffer_get(void); static void ipp_buffer_release(unsigned char *b); +static void ipp_free_values(ipp_attribute_t *attr, int element, int count); +static char *ipp_get_code(const char *locale, char *buffer, size_t bufsize); +static char *ipp_lang_code(const char *locale, char *buffer, size_t bufsize); static size_t ipp_length(ipp_t *ipp, int collection); static ssize_t ipp_read_http(http_t *http, ipp_uchar_t *buffer, size_t length); static ssize_t ipp_read_file(int *fd, ipp_uchar_t *buffer, size_t length); +static _ipp_value_t *ipp_set_value(ipp_t *ipp, ipp_attribute_t **attr, int element); static ssize_t ipp_write_file(int *fd, ipp_uchar_t *buffer, size_t length); /* * 'ippAddBoolean()' - Add a boolean attribute to an IPP message. + * + * The @code ipp@ parameter refers to an IPP message previously created using the + * @link ippNew@ or @link ippNewRequest@ functions. + * + * The @code group@ parameter specifies the IPP attribute group tag: none + * (@code IPP_TAG_ZERO@, for member attributes), document (@code IPP_TAG_DOCUMENT@), + * event notification (@code IPP_TAG_EVENT_NOTIFICATION@), operation + * (@code IPP_TAG_OPERATION@), printer (@code IPP_TAG_PRINTER@), subscription + * (@code IPP_TAG_SUBSCRIPTION@), or unsupported (@code IPP_TAG_UNSUPPORTED_GROUP@). */ ipp_attribute_t * /* O - New attribute */ @@ -97,15 +158,21 @@ ippAddBoolean(ipp_t *ipp, /* I - IPP message */ DEBUG_printf(("ippAddBoolean(ipp=%p, group=%02x(%s), name=\"%s\", value=%d)", ipp, group, ippTagString(group), name, value)); - if (!ipp || !name) + /* + * Range check input... + */ + + if (!ipp || !name || group < IPP_TAG_ZERO || + group == IPP_TAG_END || group >= IPP_TAG_UNSUPPORTED_VALUE) return (NULL); - if ((attr = _ippAddAttr(ipp, 1)) == NULL) + /* + * Create the attribute... + */ + + if ((attr = ipp_add_attr(ipp, name, group, IPP_TAG_BOOLEAN, 1)) == NULL) return (NULL); - attr->name = _cupsStrAlloc(name); - attr->group_tag = group; - attr->value_tag = IPP_TAG_BOOLEAN; attr->values[0].boolean = value; return (attr); @@ -114,6 +181,15 @@ ippAddBoolean(ipp_t *ipp, /* I - IPP message */ /* * 'ippAddBooleans()' - Add an array of boolean values. + * + * The @code ipp@ parameter refers to an IPP message previously created using the + * @link ippNew@ or @link ippNewRequest@ functions. + * + * The @code group@ parameter specifies the IPP attribute group tag: none + * (@code IPP_TAG_ZERO@, for member attributes), document (@code IPP_TAG_DOCUMENT@), + * event notification (@code IPP_TAG_EVENT_NOTIFICATION@), operation + * (@code IPP_TAG_OPERATION@), printer (@code IPP_TAG_PRINTER@), subscription + * (@code IPP_TAG_SUBSCRIPTION@), or unsupported (@code IPP_TAG_UNSUPPORTED_GROUP@). */ ipp_attribute_t * /* O - New attribute */ @@ -125,28 +201,36 @@ ippAddBooleans(ipp_t *ipp, /* I - IPP message */ { int i; /* Looping var */ ipp_attribute_t *attr; /* New attribute */ - ipp_value_t *value; /* Current value */ + _ipp_value_t *value; /* Current value */ DEBUG_printf(("ippAddBooleans(ipp=%p, group=%02x(%s), name=\"%s\", " "num_values=%d, values=%p)", ipp, group, ippTagString(group), name, num_values, values)); - if (!ipp || !name || num_values < 1) - return (NULL); + /* + * Range check input... + */ - if ((attr = _ippAddAttr(ipp, num_values)) == NULL) + if (!ipp || !name || group < IPP_TAG_ZERO || + group == IPP_TAG_END || group >= IPP_TAG_UNSUPPORTED_VALUE || + num_values < 1) return (NULL); - attr->name = _cupsStrAlloc(name); - attr->group_tag = group; - attr->value_tag = IPP_TAG_BOOLEAN; + /* + * Create the attribute... + */ + + if ((attr = ipp_add_attr(ipp, name, group, IPP_TAG_BOOLEAN, num_values)) == NULL) + return (NULL); - if (values != NULL) - for (i = 0, value = attr->values; - i < num_values; - i ++, value ++) - value->boolean = values[i]; + if (values) + { + for (i = num_values, value = attr->values; + i > 0; + i --, value ++) + value->boolean = *values++; + } return (attr); } @@ -155,6 +239,15 @@ ippAddBooleans(ipp_t *ipp, /* I - IPP message */ /* * 'ippAddCollection()' - Add a collection value. * + * The @code ipp@ parameter refers to an IPP message previously created using the + * @link ippNew@ or @link ippNewRequest@ functions. + * + * The @code group@ parameter specifies the IPP attribute group tag: none + * (@code IPP_TAG_ZERO@, for member attributes), document (@code IPP_TAG_DOCUMENT@), + * event notification (@code IPP_TAG_EVENT_NOTIFICATION@), operation + * (@code IPP_TAG_OPERATION@), printer (@code IPP_TAG_PRINTER@), subscription + * (@code IPP_TAG_SUBSCRIPTION@), or unsupported (@code IPP_TAG_UNSUPPORTED_GROUP@). + * * @since CUPS 1.1.19/Mac OS X 10.3@ */ @@ -170,15 +263,21 @@ ippAddCollection(ipp_t *ipp, /* I - IPP message */ DEBUG_printf(("ippAddCollection(ipp=%p, group=%02x(%s), name=\"%s\", " "value=%p)", ipp, group, ippTagString(group), name, value)); - if (!ipp || !name) + /* + * Range check input... + */ + + if (!ipp || !name || group < IPP_TAG_ZERO || + group == IPP_TAG_END || group >= IPP_TAG_UNSUPPORTED_VALUE) return (NULL); - if ((attr = _ippAddAttr(ipp, 1)) == NULL) + /* + * Create the attribute... + */ + + if ((attr = ipp_add_attr(ipp, name, group, IPP_TAG_BEGIN_COLLECTION, 1)) == NULL) return (NULL); - attr->name = _cupsStrAlloc(name); - attr->group_tag = group; - attr->value_tag = IPP_TAG_BEGIN_COLLECTION; attr->values[0].collection = value; value->use ++; @@ -190,6 +289,15 @@ ippAddCollection(ipp_t *ipp, /* I - IPP message */ /* * 'ippAddCollections()' - Add an array of collection values. * + * The @code ipp@ parameter refers to an IPP message previously created using the + * @link ippNew@ or @link ippNewRequest@ functions. + * + * The @code group@ parameter specifies the IPP attribute group tag: none + * (@code IPP_TAG_ZERO@, for member attributes), document (@code IPP_TAG_DOCUMENT@), + * event notification (@code IPP_TAG_EVENT_NOTIFICATION@), operation + * (@code IPP_TAG_OPERATION@), printer (@code IPP_TAG_PRINTER@), subscription + * (@code IPP_TAG_SUBSCRIPTION@), or unsupported (@code IPP_TAG_UNSUPPORTED_GROUP@). + * * @since CUPS 1.1.19/Mac OS X 10.3@ */ @@ -203,30 +311,37 @@ ippAddCollections( { int i; /* Looping var */ ipp_attribute_t *attr; /* New attribute */ - ipp_value_t *value; /* Current value */ + _ipp_value_t *value; /* Current value */ DEBUG_printf(("ippAddCollections(ipp=%p, group=%02x(%s), name=\"%s\", " "num_values=%d, values=%p)", ipp, group, ippTagString(group), name, num_values, values)); - if (!ipp || !name || num_values < 1) - return (NULL); + /* + * Range check input... + */ - if ((attr = _ippAddAttr(ipp, num_values)) == NULL) + if (!ipp || !name || group < IPP_TAG_ZERO || + group == IPP_TAG_END || group >= IPP_TAG_UNSUPPORTED_VALUE || + num_values < 1) return (NULL); - attr->name = _cupsStrAlloc(name); - attr->group_tag = group; - attr->value_tag = IPP_TAG_BEGIN_COLLECTION; + /* + * Create the attribute... + */ + + if ((attr = ipp_add_attr(ipp, name, group, IPP_TAG_BEGIN_COLLECTION, + num_values)) == NULL) + return (NULL); - if (values != NULL) + if (values) { - for (i = 0, value = attr->values; - i < num_values; - i ++, value ++) + for (i = num_values, value = attr->values; + i > 0; + i --, value ++) { - value->collection = (ipp_t *)values[i]; + value->collection = (ipp_t *)*values++; value->collection->use ++; } } @@ -237,6 +352,15 @@ ippAddCollections( /* * 'ippAddDate()' - Add a date attribute to an IPP message. + * + * The @code ipp@ parameter refers to an IPP message previously created using the + * @link ippNew@ or @link ippNewRequest@ functions. + * + * The @code group@ parameter specifies the IPP attribute group tag: none + * (@code IPP_TAG_ZERO@, for member attributes), document (@code IPP_TAG_DOCUMENT@), + * event notification (@code IPP_TAG_EVENT_NOTIFICATION@), operation + * (@code IPP_TAG_OPERATION@), printer (@code IPP_TAG_PRINTER@), subscription + * (@code IPP_TAG_SUBSCRIPTION@), or unsupported (@code IPP_TAG_UNSUPPORTED_GROUP@). */ ipp_attribute_t * /* O - New attribute */ @@ -251,15 +375,21 @@ ippAddDate(ipp_t *ipp, /* I - IPP message */ DEBUG_printf(("ippAddDate(ipp=%p, group=%02x(%s), name=\"%s\", value=%p)", ipp, group, ippTagString(group), name, value)); - if (!ipp || !name || !value) + /* + * Range check input... + */ + + if (!ipp || !name || !value || group < IPP_TAG_ZERO || + group == IPP_TAG_END || group >= IPP_TAG_UNSUPPORTED_VALUE) return (NULL); - if ((attr = _ippAddAttr(ipp, 1)) == NULL) + /* + * Create the attribute... + */ + + if ((attr = ipp_add_attr(ipp, name, group, IPP_TAG_DATE, 1)) == NULL) return (NULL); - attr->name = _cupsStrAlloc(name); - attr->group_tag = group; - attr->value_tag = IPP_TAG_DATE; memcpy(attr->values[0].date, value, 11); return (attr); @@ -268,12 +398,24 @@ ippAddDate(ipp_t *ipp, /* I - IPP message */ /* * 'ippAddInteger()' - Add a integer attribute to an IPP message. + * + * The @code ipp@ parameter refers to an IPP message previously created using the + * @link ippNew@ or @link ippNewRequest@ functions. + * + * The @code group@ parameter specifies the IPP attribute group tag: none + * (@code IPP_TAG_ZERO@, for member attributes), document (@code IPP_TAG_DOCUMENT@), + * event notification (@code IPP_TAG_EVENT_NOTIFICATION@), operation + * (@code IPP_TAG_OPERATION@), printer (@code IPP_TAG_PRINTER@), subscription + * (@code IPP_TAG_SUBSCRIPTION@), or unsupported (@code IPP_TAG_UNSUPPORTED_GROUP@). + * + * Supported values include enum (@code IPP_TAG_ENUM@) and integer + * (@code IPP_TAG_INTEGER@). */ ipp_attribute_t * /* O - New attribute */ ippAddInteger(ipp_t *ipp, /* I - IPP message */ ipp_tag_t group, /* I - IPP group */ - ipp_tag_t type, /* I - Type of attribute */ + ipp_tag_t value_tag, /* I - Type of attribute */ const char *name, /* I - Name of attribute */ int value) /* I - Value of attribute */ { @@ -282,17 +424,40 @@ ippAddInteger(ipp_t *ipp, /* I - IPP message */ DEBUG_printf(("ippAddInteger(ipp=%p, group=%02x(%s), type=%02x(%s), " "name=\"%s\", value=%d)", ipp, group, ippTagString(group), - type, ippTagString(type), name, value)); + value_tag, ippTagString(value_tag), name, value)); - if (!ipp || !name) + value_tag &= IPP_TAG_MASK; + + /* + * Special-case for legacy usage: map out-of-band attributes to new ippAddOutOfBand + * function... + */ + + if (value_tag >= IPP_TAG_UNSUPPORTED_VALUE && value_tag <= IPP_TAG_ADMINDEFINE) + return (ippAddOutOfBand(ipp, group, value_tag, name)); + + /* + * Range check input... + */ + +#if 0 + if (!ipp || !name || group < IPP_TAG_ZERO || + group == IPP_TAG_END || group >= IPP_TAG_UNSUPPORTED_VALUE || + (value_tag != IPP_TAG_INTEGER && value_tag != IPP_TAG_ENUM)) + return (NULL); +#else + if (!ipp || !name || group < IPP_TAG_ZERO || + group == IPP_TAG_END || group >= IPP_TAG_UNSUPPORTED_VALUE) return (NULL); +#endif /* 0 */ - if ((attr = _ippAddAttr(ipp, 1)) == NULL) + /* + * Create the attribute... + */ + + if ((attr = ipp_add_attr(ipp, name, group, value_tag, 1)) == NULL) return (NULL); - attr->name = _cupsStrAlloc(name); - attr->group_tag = group; - attr->value_tag = type; attr->values[0].integer = value; return (attr); @@ -301,41 +466,71 @@ ippAddInteger(ipp_t *ipp, /* I - IPP message */ /* * 'ippAddIntegers()' - Add an array of integer values. + * + * The @code ipp@ parameter refers to an IPP message previously created using the + * @link ippNew@ or @link ippNewRequest@ functions. + * + * The @code group@ parameter specifies the IPP attribute group tag: none + * (@code IPP_TAG_ZERO@, for member attributes), document (@code IPP_TAG_DOCUMENT@), + * event notification (@code IPP_TAG_EVENT_NOTIFICATION@), operation + * (@code IPP_TAG_OPERATION@), printer (@code IPP_TAG_PRINTER@), subscription + * (@code IPP_TAG_SUBSCRIPTION@), or unsupported (@code IPP_TAG_UNSUPPORTED_GROUP@). + * + * Supported values include enum (@code IPP_TAG_ENUM@) and integer + * (@code IPP_TAG_INTEGER@). */ ipp_attribute_t * /* O - New attribute */ ippAddIntegers(ipp_t *ipp, /* I - IPP message */ ipp_tag_t group, /* I - IPP group */ - ipp_tag_t type, /* I - Type of attribute */ + ipp_tag_t value_tag, /* I - Type of attribute */ const char *name, /* I - Name of attribute */ int num_values, /* I - Number of values */ const int *values) /* I - Values */ { int i; /* Looping var */ ipp_attribute_t *attr; /* New attribute */ - ipp_value_t *value; /* Current value */ + _ipp_value_t *value; /* Current value */ DEBUG_printf(("ippAddIntegers(ipp=%p, group=%02x(%s), type=%02x(%s), " "name=\"%s\", num_values=%d, values=%p)", ipp, - group, ippTagString(group), type, ippTagString(type), name, + group, ippTagString(group), value_tag, ippTagString(value_tag), name, num_values, values)); - if (!ipp || !name || num_values < 1) - return (NULL); + value_tag &= IPP_TAG_MASK; + + /* + * Range check input... + */ - if ((attr = _ippAddAttr(ipp, num_values)) == NULL) +#if 0 + if (!ipp || !name || group < IPP_TAG_ZERO || + group == IPP_TAG_END || group >= IPP_TAG_UNSUPPORTED_VALUE || + (value_tag != IPP_TAG_INTEGER && value_tag != IPP_TAG_ENUM) || + num_values < 1) + return (NULL); +#else + if (!ipp || !name || group < IPP_TAG_ZERO || + group == IPP_TAG_END || group >= IPP_TAG_UNSUPPORTED_VALUE || + num_values < 1) return (NULL); +#endif /* 0 */ - attr->name = _cupsStrAlloc(name); - attr->group_tag = group; - attr->value_tag = type; + /* + * Create the attribute... + */ + + if ((attr = ipp_add_attr(ipp, name, group, value_tag, num_values)) == NULL) + return (NULL); - if (values != NULL) - for (i = 0, value = attr->values; - i < num_values; - i ++, value ++) - value->integer = values[i]; + if (values) + { + for (i = num_values, value = attr->values; + i > 0; + i --, value ++) + value->integer = *values++; + } return (attr); } @@ -344,6 +539,15 @@ ippAddIntegers(ipp_t *ipp, /* I - IPP message */ /* * 'ippAddOctetString()' - Add an octetString value to an IPP message. * + * The @code ipp@ parameter refers to an IPP message previously created using the + * @link ippNew@ or @link ippNewRequest@ functions. + * + * The @code group@ parameter specifies the IPP attribute group tag: none + * (@code IPP_TAG_ZERO@, for member attributes), document (@code IPP_TAG_DOCUMENT@), + * event notification (@code IPP_TAG_EVENT_NOTIFICATION@), operation + * (@code IPP_TAG_OPERATION@), printer (@code IPP_TAG_PRINTER@), subscription + * (@code IPP_TAG_SUBSCRIPTION@), or unsupported (@code IPP_TAG_UNSUPPORTED_GROUP@). + * * @since CUPS 1.2/Mac OS X 10.5@ */ @@ -357,19 +561,17 @@ ippAddOctetString(ipp_t *ipp, /* I - IPP message */ ipp_attribute_t *attr; /* New attribute */ - if (ipp == NULL || name == NULL) + if (!ipp || !name || group < IPP_TAG_ZERO || + group == IPP_TAG_END || group >= IPP_TAG_UNSUPPORTED_VALUE) return (NULL); - if ((attr = _ippAddAttr(ipp, 1)) == NULL) + if ((attr = ipp_add_attr(ipp, name, group, IPP_TAG_STRING, 1)) == NULL) return (NULL); /* * Initialize the attribute data... */ - attr->name = _cupsStrAlloc(name); - attr->group_tag = group; - attr->value_tag = IPP_TAG_STRING; attr->values[0].unknown.length = datalen; if (data) @@ -392,164 +594,74 @@ ippAddOctetString(ipp_t *ipp, /* I - IPP message */ /* - * 'ippAddString()' - Add a language-encoded string to an IPP message. + * 'ippAddOutOfBand()' - Add an out-of-band value to an IPP message. + * + * The @code ipp@ parameter refers to an IPP message previously created using the + * @link ippNew@ or @link ippNewRequest@ functions. + * + * The @code group@ parameter specifies the IPP attribute group tag: none + * (@code IPP_TAG_ZERO@, for member attributes), document (@code IPP_TAG_DOCUMENT@), + * event notification (@code IPP_TAG_EVENT_NOTIFICATION@), operation + * (@code IPP_TAG_OPERATION@), printer (@code IPP_TAG_PRINTER@), subscription + * (@code IPP_TAG_SUBSCRIPTION@), or unsupported (@code IPP_TAG_UNSUPPORTED_GROUP@). + * + * Supported out-of-band values include unsupported-value + * (@code IPP_TAG_UNSUPPORTED_VALUE@), default (@code IPP_TAG_DEFAULT@), unknown + * (@code IPP_TAG_UNKNOWN@), no-value (@code IPP_TAG_NOVALUE@), not-settable + * (@code IPP_TAG_NOTSETTABLE@), delete-attribute (@code IPP_TAG_DELETEATTR@), and + * admin-define (@code IPP_TAG_ADMINDEFINE@). + * + * @since CUPS 1.6@ */ -ipp_attribute_t * /* O - New attribute */ -ippAddString(ipp_t *ipp, /* I - IPP message */ - ipp_tag_t group, /* I - IPP group */ - ipp_tag_t type, /* I - Type of attribute */ - const char *name, /* I - Name of attribute */ - const char *charset, /* I - Character set */ - const char *value) /* I - Value */ +ipp_attribute_t * /* O - New attribute */ +ippAddOutOfBand(ipp_t *ipp, /* I - IPP message */ + ipp_tag_t group, /* I - IPP group */ + ipp_tag_t value_tag, /* I - Type of attribute */ + const char *name) /* I - Name of attribute */ { - ipp_attribute_t *attr; /* New attribute */ - char buffer[1024], /* Language/charset value buffer */ - *bufptr; /* Pointer into buffer */ - - - DEBUG_printf(("ippAddString(ipp=%p, group=%02x(%s), type=%02x(%s), " - "name=\"%s\", charset=\"%s\", value=\"%s\")", ipp, - group, ippTagString(group), type, ippTagString(type), name, - charset, value)); - - if (!ipp || !name) - return (NULL); - - if ((attr = _ippAddAttr(ipp, 1)) == NULL) - return (NULL); - - /* - * Force value to be English for the POSIX locale... - */ - - if (type == IPP_TAG_LANGUAGE && !_cups_strcasecmp(value, "C")) - value = "en"; + DEBUG_printf(("ippAddOutOfBand(ipp=%p, group=%02x(%s), value_tag=%02x(%s), " + "name=\"%s\")", ipp, group, ippTagString(group), value_tag, + ippTagString(value_tag), name)); - /* - * Convert language and charset values to lowercase and change _ to - as - * needed... - */ - - if ((type == IPP_TAG_LANGUAGE || type == IPP_TAG_CHARSET) && value) - { - strlcpy(buffer, value, sizeof(buffer)); - value = buffer; - - for (bufptr = buffer; *bufptr; bufptr ++) - if (*bufptr == '_') - *bufptr = '-'; - else - *bufptr = tolower(*bufptr & 255); - } + value_tag &= IPP_TAG_MASK; /* - * Initialize the attribute data... + * Range check input... */ - attr->name = _cupsStrAlloc(name); - attr->group_tag = group; - attr->value_tag = type; - attr->values[0].string.charset = ((int)type & IPP_TAG_COPY) ? (char *)charset : - charset ? _cupsStrAlloc(charset) : NULL; - attr->values[0].string.text = ((int)type & IPP_TAG_COPY) ? (char *)value : - value ? _cupsStrAlloc(value) : NULL; - - return (attr); -} - - -/* - * 'ippAddStrings()' - Add language-encoded strings to an IPP message. - */ - -ipp_attribute_t * /* O - New attribute */ -ippAddStrings( - ipp_t *ipp, /* I - IPP message */ - ipp_tag_t group, /* I - IPP group */ - ipp_tag_t type, /* I - Type of attribute */ - const char *name, /* I - Name of attribute */ - int num_values, /* I - Number of values */ - const char *charset, /* I - Character set */ - const char * const *values) /* I - Values */ -{ - int i; /* Looping var */ - ipp_attribute_t *attr; /* New attribute */ - ipp_value_t *value; /* Current value */ - char buffer[1024], /* Language/charset value buffer */ - *bufptr; /* Pointer into buffer */ - - - DEBUG_printf(("ippAddStrings(ipp=%p, group=%02x(%s), type=%02x(%s), " - "name=\"%s\", num_values=%d, charset=\"%s\", values=%p)", ipp, - group, ippTagString(group), type, ippTagString(type), name, - num_values, charset, values)); - - if (!ipp || !name || num_values < 1) - return (NULL); - - if ((attr = _ippAddAttr(ipp, num_values)) == NULL) + if (!ipp || !name || group < IPP_TAG_ZERO || + group == IPP_TAG_END || group >= IPP_TAG_UNSUPPORTED_VALUE || + (value_tag != IPP_TAG_UNSUPPORTED_VALUE && + value_tag != IPP_TAG_DEFAULT && + value_tag != IPP_TAG_UNKNOWN && + value_tag != IPP_TAG_NOVALUE && + value_tag != IPP_TAG_NOTSETTABLE && + value_tag != IPP_TAG_DELETEATTR && + value_tag != IPP_TAG_ADMINDEFINE)) return (NULL); /* - * Initialize the attribute data... + * Create the attribute... */ - attr->name = _cupsStrAlloc(name); - attr->group_tag = group; - attr->value_tag = type; - - for (i = 0, value = attr->values; - i < num_values; - i ++, value ++) - { - if (i == 0) - value->string.charset = ((int)type & IPP_TAG_COPY) ? (char *)charset : - charset ? _cupsStrAlloc(charset) : NULL; - else - value->string.charset = attr->values[0].string.charset; - - if (values != NULL) - { - if ((int)type & IPP_TAG_COPY) - value->string.text = (char *)values[i]; - else if (type == IPP_TAG_LANGUAGE && !_cups_strcasecmp(values[i], "C")) - { - /* - * Force language to be English for the POSIX locale... - */ - - value->string.text = ((int)type & IPP_TAG_COPY) ? "en" : - _cupsStrAlloc("en"); - } - else if (type == IPP_TAG_LANGUAGE || type == IPP_TAG_CHARSET) - { - /* - * Convert language values to lowercase and change _ to - as needed... - */ - - strlcpy(buffer, values[i], sizeof(buffer)); - - for (bufptr = buffer; *bufptr; bufptr ++) - if (*bufptr == '_') - *bufptr = '-'; - else - *bufptr = tolower(*bufptr & 255); - - value->string.text = _cupsStrAlloc(buffer); - } - else - value->string.text = _cupsStrAlloc(values[i]); - - } - } - - return (attr); + return (ipp_add_attr(ipp, name, group, value_tag, 1)); } /* * 'ippAddRange()' - Add a range of values to an IPP message. + * + * The @code ipp@ parameter refers to an IPP message previously created using the + * @link ippNew@ or @link ippNewRequest@ functions. + * + * The @code group@ parameter specifies the IPP attribute group tag: none + * (@code IPP_TAG_ZERO@, for member attributes), document (@code IPP_TAG_DOCUMENT@), + * event notification (@code IPP_TAG_EVENT_NOTIFICATION@), operation + * (@code IPP_TAG_OPERATION@), printer (@code IPP_TAG_PRINTER@), subscription + * (@code IPP_TAG_SUBSCRIPTION@), or unsupported (@code IPP_TAG_UNSUPPORTED_GROUP@). + * + * The @code lower@ parameter must be less than or equal to the @code upper@ parameter. */ ipp_attribute_t * /* O - New attribute */ @@ -566,15 +678,21 @@ ippAddRange(ipp_t *ipp, /* I - IPP message */ "upper=%d)", ipp, group, ippTagString(group), name, lower, upper)); - if (!ipp || !name) + /* + * Range check input... + */ + + if (!ipp || !name || group < IPP_TAG_ZERO || + group == IPP_TAG_END || group >= IPP_TAG_UNSUPPORTED_VALUE) return (NULL); - if ((attr = _ippAddAttr(ipp, 1)) == NULL) + /* + * Create the attribute... + */ + + if ((attr = ipp_add_attr(ipp, name, group, IPP_TAG_RANGE, 1)) == NULL) return (NULL); - attr->name = _cupsStrAlloc(name); - attr->group_tag = group; - attr->value_tag = IPP_TAG_RANGE; attr->values[0].range.lower = lower; attr->values[0].range.upper = upper; @@ -584,6 +702,15 @@ ippAddRange(ipp_t *ipp, /* I - IPP message */ /* * 'ippAddRanges()' - Add ranges of values to an IPP message. + * + * The @code ipp@ parameter refers to an IPP message previously created using the + * @link ippNew@ or @link ippNewRequest@ functions. + * + * The @code group@ parameter specifies the IPP attribute group tag: none + * (@code IPP_TAG_ZERO@, for member attributes), document (@code IPP_TAG_DOCUMENT@), + * event notification (@code IPP_TAG_EVENT_NOTIFICATION@), operation + * (@code IPP_TAG_OPERATION@), printer (@code IPP_TAG_PRINTER@), subscription + * (@code IPP_TAG_SUBSCRIPTION@), or unsupported (@code IPP_TAG_UNSUPPORTED_GROUP@). */ ipp_attribute_t * /* O - New attribute */ @@ -596,31 +723,39 @@ ippAddRanges(ipp_t *ipp, /* I - IPP message */ { int i; /* Looping var */ ipp_attribute_t *attr; /* New attribute */ - ipp_value_t *value; /* Current value */ + _ipp_value_t *value; /* Current value */ DEBUG_printf(("ippAddRanges(ipp=%p, group=%02x(%s), name=\"%s\", " "num_values=%d, lower=%p, upper=%p)", ipp, group, ippTagString(group), name, num_values, lower, upper)); - if (!ipp || !name || num_values < 1) - return (NULL); + /* + * Range check input... + */ - if ((attr = _ippAddAttr(ipp, num_values)) == NULL) + if (!ipp || !name || group < IPP_TAG_ZERO || + group == IPP_TAG_END || group >= IPP_TAG_UNSUPPORTED_VALUE || + num_values < 1) return (NULL); - attr->name = _cupsStrAlloc(name); - attr->group_tag = group; - attr->value_tag = IPP_TAG_RANGE; + /* + * Create the attribute... + */ + + if ((attr = ipp_add_attr(ipp, name, group, IPP_TAG_RANGE, num_values)) == NULL) + return (NULL); - if (lower != NULL && upper != NULL) - for (i = 0, value = attr->values; - i < num_values; - i ++, value ++) + if (lower && upper) + { + for (i = num_values, value = attr->values; + i > 0; + i --, value ++) { - value->range.lower = lower[i]; - value->range.upper = upper[i]; + value->range.lower = *lower++; + value->range.upper = *upper++; } + } return (attr); } @@ -628,6 +763,15 @@ ippAddRanges(ipp_t *ipp, /* I - IPP message */ /* * 'ippAddResolution()' - Add a resolution value to an IPP message. + * + * The @code ipp@ parameter refers to an IPP message previously created using the + * @link ippNew@ or @link ippNewRequest@ functions. + * + * The @code group@ parameter specifies the IPP attribute group tag: none + * (@code IPP_TAG_ZERO@, for member attributes), document (@code IPP_TAG_DOCUMENT@), + * event notification (@code IPP_TAG_EVENT_NOTIFICATION@), operation + * (@code IPP_TAG_OPERATION@), printer (@code IPP_TAG_PRINTER@), subscription + * (@code IPP_TAG_SUBSCRIPTION@), or unsupported (@code IPP_TAG_UNSUPPORTED_GROUP@). */ ipp_attribute_t * /* O - New attribute */ @@ -645,15 +789,23 @@ ippAddResolution(ipp_t *ipp, /* I - IPP message */ "units=%d, xres=%d, yres=%d)", ipp, group, ippTagString(group), name, units, xres, yres)); - if (!ipp || !name) + /* + * Range check input... + */ + + if (!ipp || !name || group < IPP_TAG_ZERO || + group == IPP_TAG_END || group >= IPP_TAG_UNSUPPORTED_VALUE || + units < IPP_RES_PER_INCH || units > IPP_RES_PER_CM || + xres < 0 || yres < 0) return (NULL); - if ((attr = _ippAddAttr(ipp, 1)) == NULL) + /* + * Create the attribute... + */ + + if ((attr = ipp_add_attr(ipp, name, group, IPP_TAG_RESOLUTION, 1)) == NULL) return (NULL); - attr->name = _cupsStrAlloc(name); - attr->group_tag = group; - attr->value_tag = IPP_TAG_RESOLUTION; attr->values[0].resolution.xres = xres; attr->values[0].resolution.yres = yres; attr->values[0].resolution.units = units; @@ -664,6 +816,15 @@ ippAddResolution(ipp_t *ipp, /* I - IPP message */ /* * 'ippAddResolutions()' - Add resolution values to an IPP message. + * + * The @code ipp@ parameter refers to an IPP message previously created using the + * @link ippNew@ or @link ippNewRequest@ functions. + * + * The @code group@ parameter specifies the IPP attribute group tag: none + * (@code IPP_TAG_ZERO@, for member attributes), document (@code IPP_TAG_DOCUMENT@), + * event notification (@code IPP_TAG_EVENT_NOTIFICATION@), operation + * (@code IPP_TAG_OPERATION@), printer (@code IPP_TAG_PRINTER@), subscription + * (@code IPP_TAG_SUBSCRIPTION@), or unsupported (@code IPP_TAG_UNSUPPORTED_GROUP@). */ ipp_attribute_t * /* O - New attribute */ @@ -677,32 +838,41 @@ ippAddResolutions(ipp_t *ipp, /* I - IPP message */ { int i; /* Looping var */ ipp_attribute_t *attr; /* New attribute */ - ipp_value_t *value; /* Current value */ + _ipp_value_t *value; /* Current value */ DEBUG_printf(("ippAddResolutions(ipp=%p, group=%02x(%s), name=\"%s\", " "num_value=%d, units=%d, xres=%p, yres=%p)", ipp, group, ippTagString(group), name, num_values, units, xres, yres)); - if (!ipp || !name || num_values < 1) - return (NULL); + /* + * Range check input... + */ - if ((attr = _ippAddAttr(ipp, num_values)) == NULL) + if (!ipp || !name || group < IPP_TAG_ZERO || + group == IPP_TAG_END || group >= IPP_TAG_UNSUPPORTED_VALUE || + num_values < 1 || + units < IPP_RES_PER_INCH || units > IPP_RES_PER_CM) return (NULL); - attr->name = _cupsStrAlloc(name); - attr->group_tag = group; - attr->value_tag = IPP_TAG_RESOLUTION; + /* + * Create the attribute... + */ + + if ((attr = ipp_add_attr(ipp, name, group, IPP_TAG_RESOLUTION, num_values)) == NULL) + return (NULL); - if (xres != NULL && yres != NULL) - for (i = 0, value = attr->values; - i < num_values; - i ++, value ++) + if (xres && yres) + { + for (i = num_values, value = attr->values; + i > 0; + i --, value ++) { - value->resolution.xres = xres[i]; - value->resolution.yres = yres[i]; + value->resolution.xres = *xres++; + value->resolution.yres = *yres++; value->resolution.units = units; } + } return (attr); } @@ -710,504 +880,1571 @@ ippAddResolutions(ipp_t *ipp, /* I - IPP message */ /* * 'ippAddSeparator()' - Add a group separator to an IPP message. + * + * The @code ipp@ parameter refers to an IPP message previously created using the + * @link ippNew@ or @link ippNewRequest@ functions. */ ipp_attribute_t * /* O - New attribute */ ippAddSeparator(ipp_t *ipp) /* I - IPP message */ { - ipp_attribute_t *attr; /* New attribute */ - - DEBUG_printf(("ippAddSeparator(ipp=%p)", ipp)); - if (!ipp) - return (NULL); + /* + * Range check input... + */ - if ((attr = _ippAddAttr(ipp, 0)) == NULL) + if (!ipp) return (NULL); - attr->group_tag = IPP_TAG_ZERO; - attr->value_tag = IPP_TAG_ZERO; + /* + * Create the attribute... + */ - return (attr); + return (ipp_add_attr(ipp, NULL, IPP_TAG_ZERO, IPP_TAG_ZERO, 0)); } /* - * 'ippDateToTime()' - Convert from RFC 1903 Date/Time format to UNIX time - * in seconds. + * 'ippAddString()' - Add a language-encoded string to an IPP message. + * + * The @code ipp@ parameter refers to an IPP message previously created using the + * @link ippNew@ or @link ippNewRequest@ functions. + * + * The @code group@ parameter specifies the IPP attribute group tag: none + * (@code IPP_TAG_ZERO@, for member attributes), document (@code IPP_TAG_DOCUMENT@), + * event notification (@code IPP_TAG_EVENT_NOTIFICATION@), operation + * (@code IPP_TAG_OPERATION@), printer (@code IPP_TAG_PRINTER@), subscription + * (@code IPP_TAG_SUBSCRIPTION@), or unsupported (@code IPP_TAG_UNSUPPORTED_GROUP@). + * + * Supported string values include charset (@code IPP_TAG_CHARSET@), keyword + * (@code IPP_TAG_KEYWORD@), language (@code IPP_TAG_LANGUAGE@), mimeMediaType + * (@code IPP_TAG_MIMETYPE@), name (@code IPP_TAG_NAME@), nameWithLanguage + * (@code IPP_TAG_NAMELANG), text (@code IPP_TAG_TEXT@), textWithLanguage + * (@code IPP_TAG_TEXTLANG@), uri (@code IPP_TAG_URI@), and uriScheme + * (@code IPP_TAG_URISCHEME@). + * + * The @code language@ parameter must be non-@code NULL@ for nameWithLanguage and + * textWithLanguage string values and must be @code NULL@ for all other string values. */ -time_t /* O - UNIX time value */ -ippDateToTime(const ipp_uchar_t *date) /* I - RFC 1903 date info */ +ipp_attribute_t * /* O - New attribute */ +ippAddString(ipp_t *ipp, /* I - IPP message */ + ipp_tag_t group, /* I - IPP group */ + ipp_tag_t value_tag, /* I - Type of attribute */ + const char *name, /* I - Name of attribute */ + const char *language, /* I - Language code */ + const char *value) /* I - Value */ { - struct tm unixdate; /* UNIX date/time info */ - time_t t; /* Computed time */ - + ipp_tag_t temp_tag; /* Temporary value tag (masked) */ + ipp_attribute_t *attr; /* New attribute */ + char code[32]; /* Charset/language code buffer */ - if (!date) - return (0); - memset(&unixdate, 0, sizeof(unixdate)); + DEBUG_printf(("ippAddString(ipp=%p, group=%02x(%s), value_tag=%02x(%s), " + "name=\"%s\", language=\"%s\", value=\"%s\")", ipp, + group, ippTagString(group), value_tag, ippTagString(value_tag), name, + language, value)); /* - * RFC-1903 date/time format is: - * - * Byte(s) Description - * ------- ----------- - * 0-1 Year (0 to 65535) - * 2 Month (1 to 12) - * 3 Day (1 to 31) - * 4 Hours (0 to 23) - * 5 Minutes (0 to 59) - * 6 Seconds (0 to 60, 60 = "leap second") - * 7 Deciseconds (0 to 9) - * 8 +/- UTC - * 9 UTC hours (0 to 11) - * 10 UTC minutes (0 to 59) + * Range check input... */ - unixdate.tm_year = ((date[0] << 8) | date[1]) - 1900; - unixdate.tm_mon = date[2] - 1; - unixdate.tm_mday = date[3]; - unixdate.tm_hour = date[4]; - unixdate.tm_min = date[5]; - unixdate.tm_sec = date[6]; - - t = mktime(&unixdate); - - if (date[8] == '-') - t += date[9] * 3600 + date[10] * 60; - else - t -= date[9] * 3600 + date[10] * 60; - - return (t); -} + temp_tag = (ipp_tag_t)((int)value_tag & IPP_TAG_MASK); +#if 0 + if (!ipp || !name || group < IPP_TAG_ZERO || + group == IPP_TAG_END || group >= IPP_TAG_UNSUPPORTED_VALUE || + (temp_tag < IPP_TAG_TEXT && temp_tag != IPP_TAG_TEXTLANG && + temp_tag != IPP_TAG_NAMELANG) || temp_tag > IPP_TAG_MIMETYPE) + return (NULL); -/* - * 'ippDelete()' - Delete an IPP message. - */ + if ((temp_tag == IPP_TAG_TEXTLANG || temp_tag == IPP_TAG_NAMELANG) + != (language != NULL)) + return (NULL); +#else + if (!ipp || !name || group < IPP_TAG_ZERO || + group == IPP_TAG_END || group >= IPP_TAG_UNSUPPORTED_VALUE) + return (NULL); +#endif /* 0 */ -void -ippDelete(ipp_t *ipp) /* I - IPP message */ -{ - ipp_attribute_t *attr, /* Current attribute */ - *next; /* Next attribute */ + /* + * See if we need to map charset, language, or locale values... + */ + if (language && ((int)value_tag & IPP_TAG_COPY) && + strcmp(language, ipp_lang_code(language, code, sizeof(code)))) + value_tag = temp_tag; /* Don't do a fast copy */ + else if (value && value_tag == (ipp_tag_t)(IPP_TAG_CHARSET | IPP_TAG_COPY) && + strcmp(value, ipp_get_code(value, code, sizeof(code)))) + value_tag = temp_tag; /* Don't do a fast copy */ + else if (value && value_tag == (ipp_tag_t)(IPP_TAG_LANGUAGE | IPP_TAG_COPY) && + strcmp(value, ipp_lang_code(value, code, sizeof(code)))) + value_tag = temp_tag; /* Don't do a fast copy */ - DEBUG_printf(("ippDelete(ipp=%p)", ipp)); + /* + * Create the attribute... + */ - if (!ipp) - return; + if ((attr = ipp_add_attr(ipp, name, group, value_tag, 1)) == NULL) + return (NULL); - ipp->use --; - if (ipp->use > 0) - return; + /* + * Initialize the attribute data... + */ - for (attr = ipp->attrs; attr != NULL; attr = next) + if ((int)value_tag & IPP_TAG_COPY) { - next = attr->next; - _ippFreeAttr(attr); + attr->values[0].string.language = (char *)language; + attr->values[0].string.text = (char *)value; + } + else + { + if (language) + attr->values[0].string.language = _cupsStrAlloc(ipp_lang_code(language, code, + sizeof(code))); + + if (value_tag == IPP_TAG_CHARSET) + attr->values[0].string.text = _cupsStrAlloc(ipp_get_code(value, code, + sizeof(code))); + else if (value_tag == IPP_TAG_LANGUAGE) + attr->values[0].string.text = _cupsStrAlloc(ipp_lang_code(value, code, + sizeof(code))); + else + attr->values[0].string.text = _cupsStrAlloc(value); } - free(ipp); + return (attr); } /* - * 'ippDeleteAttribute()' - Delete a single attribute in an IPP message. + * 'ippAddStrings()' - Add language-encoded strings to an IPP message. * - * @since CUPS 1.1.19/Mac OS X 10.3@ + * The @code ipp@ parameter refers to an IPP message previously created using the + * @link ippNew@ or @link ippNewRequest@ functions. + * + * The @code group@ parameter specifies the IPP attribute group tag: none + * (@code IPP_TAG_ZERO@, for member attributes), document (@code IPP_TAG_DOCUMENT@), + * event notification (@code IPP_TAG_EVENT_NOTIFICATION@), operation + * (@code IPP_TAG_OPERATION@), printer (@code IPP_TAG_PRINTER@), subscription + * (@code IPP_TAG_SUBSCRIPTION@), or unsupported (@code IPP_TAG_UNSUPPORTED_GROUP@). + * + * Supported string values include charset (@code IPP_TAG_CHARSET@), keyword + * (@code IPP_TAG_KEYWORD@), language (@code IPP_TAG_LANGUAGE@), mimeMediaType + * (@code IPP_TAG_MIMETYPE@), name (@code IPP_TAG_NAME@), nameWithLanguage + * (@code IPP_TAG_NAMELANG), text (@code IPP_TAG_TEXT@), textWithLanguage + * (@code IPP_TAG_TEXTLANG@), uri (@code IPP_TAG_URI@), and uriScheme + * (@code IPP_TAG_URISCHEME@). + * + * The @code language@ parameter must be non-@code NULL@ for nameWithLanguage and + * textWithLanguage string values and must be @code NULL@ for all other string values. */ -void -ippDeleteAttribute( - ipp_t *ipp, /* I - IPP message */ - ipp_attribute_t *attr) /* I - Attribute to delete */ +ipp_attribute_t * /* O - New attribute */ +ippAddStrings( + ipp_t *ipp, /* I - IPP message */ + ipp_tag_t group, /* I - IPP group */ + ipp_tag_t value_tag, /* I - Type of attribute */ + const char *name, /* I - Name of attribute */ + int num_values, /* I - Number of values */ + const char *language, /* I - Language code (@code NULL@ for default) */ + const char * const *values) /* I - Values */ { - ipp_attribute_t *current, /* Current attribute */ - *prev; /* Previous attribute */ + int i; /* Looping var */ + ipp_tag_t temp_tag; /* Temporary value tag (masked) */ + ipp_attribute_t *attr; /* New attribute */ + _ipp_value_t *value; /* Current value */ + char code[32]; /* Language/charset value buffer */ - DEBUG_printf(("ippDeleteAttribute(ipp=%p, attr=%p(%s))", ipp, attr, - attr ? attr->name : "(null)")); + DEBUG_printf(("ippAddStrings(ipp=%p, group=%02x(%s), value_tag=%02x(%s), " + "name=\"%s\", num_values=%d, language=\"%s\", values=%p)", ipp, + group, ippTagString(group), value_tag, ippTagString(value_tag), name, + num_values, language, values)); /* - * Find the attribute in the list... + * Range check input... */ - for (current = ipp->attrs, prev = NULL; - current != NULL && current != attr; - prev = current, current = current->next); - - if (current) - { - /* - * Found it, remove the attribute from the list... - */ + temp_tag = (ipp_tag_t)((int)value_tag & IPP_TAG_MASK); - if (prev) - prev->next = current->next; - else - ipp->attrs = current->next; +#if 0 + if (!ipp || !name || group < IPP_TAG_ZERO || + group == IPP_TAG_END || group >= IPP_TAG_UNSUPPORTED_VALUE || + (temp_tag < IPP_TAG_TEXT && temp_tag != IPP_TAG_TEXTLANG && + temp_tag != IPP_TAG_NAMELANG) || temp_tag > IPP_TAG_MIMETYPE || + num_values < 1) + return (NULL); - if (current == ipp->last) - ipp->last = prev; + if ((temp_tag == IPP_TAG_TEXTLANG || temp_tag == IPP_TAG_NAMELANG) + != (language != NULL)) + return (NULL); +#else + if (!ipp || !name || group < IPP_TAG_ZERO || + group == IPP_TAG_END || group >= IPP_TAG_UNSUPPORTED_VALUE || + num_values < 1) + return (NULL); +#endif /* 0 */ - /* - * Free memory used by the attribute... - */ + /* + * See if we need to map charset, language, or locale values... + */ - _ippFreeAttr(current); + if (language && ((int)value_tag & IPP_TAG_COPY) && + strcmp(language, ipp_lang_code(language, code, sizeof(code)))) + value_tag = temp_tag; /* Don't do a fast copy */ + else if (values && value_tag == (ipp_tag_t)(IPP_TAG_CHARSET | IPP_TAG_COPY)) + { + for (i = 0; i < num_values; i ++) + if (strcmp(values[i], ipp_get_code(values[i], code, sizeof(code)))) + { + value_tag = temp_tag; /* Don't do a fast copy */ + break; + } + } + else if (values && value_tag == (ipp_tag_t)(IPP_TAG_LANGUAGE | IPP_TAG_COPY)) + { + for (i = 0; i < num_values; i ++) + if (strcmp(values[i], ipp_lang_code(values[i], code, sizeof(code)))) + { + value_tag = temp_tag; /* Don't do a fast copy */ + break; + } } -} - - -/* - * 'ippFindAttribute()' - Find a named attribute in a request... - */ -ipp_attribute_t * /* O - Matching attribute */ -ippFindAttribute(ipp_t *ipp, /* I - IPP message */ - const char *name, /* I - Name of attribute */ - ipp_tag_t type) /* I - Type of attribute */ -{ - DEBUG_printf(("2ippFindAttribute(ipp=%p, name=\"%s\", type=%02x(%s))", ipp, - name, type, ippTagString(type))); + /* + * Create the attribute... + */ - if (!ipp || !name) + if ((attr = ipp_add_attr(ipp, name, group, value_tag, num_values)) == NULL) return (NULL); /* - * Reset the current pointer... + * Initialize the attribute data... */ - ipp->current = NULL; + for (i = num_values, value = attr->values; + i > 0; + i --, value ++) + { + if (language) + { + if (value == attr->values) + { + if ((int)value_tag & IPP_TAG_COPY) + value->string.language = (char *)language; + else + value->string.language = _cupsStrAlloc(ipp_lang_code(language, code, + sizeof(code))); + } + else + value->string.language = attr->values[0].string.language; + } - /* - * Search for the attribute... - */ + if (values) + { + if ((int)value_tag & IPP_TAG_COPY) + value->string.text = (char *)*values++; + else if (value_tag == IPP_TAG_CHARSET) + value->string.text = _cupsStrAlloc(ipp_get_code(*values++, code, sizeof(code))); + else if (value_tag == IPP_TAG_LANGUAGE) + value->string.text = _cupsStrAlloc(ipp_lang_code(*values++, code, sizeof(code))); + else + value->string.text = _cupsStrAlloc(*values++); + } + } - return (ippFindNextAttribute(ipp, name, type)); + return (attr); } /* - * 'ippFindNextAttribute()' - Find the next named attribute in a request... + * 'ippCopyAttribute()' - Copy an attribute. + * + * The specified attribute, @code attr@, is copied to the destination IPP message. + * When @code quickcopy@ is non-zero, a "shallow" reference copy of the attribute is + * created - this should only be done as long as the original source IPP message will + * not be freed for the life of the destination. + * + * @since CUPS 1.6@ */ -ipp_attribute_t * /* O - Matching attribute */ -ippFindNextAttribute(ipp_t *ipp, /* I - IPP message */ - const char *name, /* I - Name of attribute */ - ipp_tag_t type) /* I - Type of attribute */ + +ipp_attribute_t * /* O - New attribute */ +ippCopyAttribute( + ipp_t *dst, /* I - Destination IPP message */ + ipp_attribute_t *srcattr, /* I - Attribute to copy */ + int quickcopy) /* I - 1 for a referenced copy, 0 for normal */ { - ipp_attribute_t *attr; /* Current atttribute */ - ipp_tag_t value_tag; /* Value tag */ + int i; /* Looping var */ + ipp_attribute_t *dstattr; /* Destination attribute */ + _ipp_value_t *srcval, /* Source value */ + *dstval; /* Destination value */ - DEBUG_printf(("2ippFindNextAttribute(ipp=%p, name=\"%s\", type=%02x(%s))", - ipp, name, type, ippTagString(type))); + DEBUG_printf(("ippCopyAttribute(dst=%p, srcattr=%p, quickcopy=%d)", dst, srcattr, + quickcopy)); - if (!ipp || !name) + /* + * Range check input... + */ + + if (!dst || !srcattr) return (NULL); - if (ipp->current) - { - ipp->prev = ipp->current; - attr = ipp->current->next; - } - else - { - ipp->prev = NULL; - attr = ipp->attrs; - } + /* + * Copy it... + */ - for (; attr != NULL; ipp->prev = attr, attr = attr->next) + quickcopy = quickcopy ? IPP_TAG_COPY : 0; + + switch (srcattr->value_tag & ~IPP_TAG_COPY) { - DEBUG_printf(("4ippFindAttribute: attr=%p, name=\"%s\"", attr, - attr->name)); + case IPP_TAG_ZERO : + dstattr = ippAddSeparator(dst); + break; - value_tag = (ipp_tag_t)(attr->value_tag & IPP_TAG_MASK); + case IPP_TAG_INTEGER : + case IPP_TAG_ENUM : + dstattr = ippAddIntegers(dst, srcattr->group_tag, srcattr->value_tag, + srcattr->name, srcattr->num_values, NULL); + if (!dstattr) + break; + + for (i = srcattr->num_values, srcval = srcattr->values, dstval = dstattr->values; + i > 0; + i --, srcval ++, dstval ++) + dstval->integer = srcval->integer; + break; - if (attr->name != NULL && _cups_strcasecmp(attr->name, name) == 0 && - (value_tag == type || type == IPP_TAG_ZERO || - (value_tag == IPP_TAG_TEXTLANG && type == IPP_TAG_TEXT) || - (value_tag == IPP_TAG_NAMELANG && type == IPP_TAG_NAME))) - { - ipp->current = attr; + case IPP_TAG_BOOLEAN : + dstattr = ippAddBooleans(dst, srcattr->group_tag, srcattr->name, + srcattr->num_values, NULL); + if (!dstattr) + break; + + for (i = srcattr->num_values, srcval = srcattr->values, dstval = dstattr->values; + i > 0; + i --, srcval ++, dstval ++) + dstval->boolean = srcval->boolean; + break; - return (attr); - } - } + case IPP_TAG_TEXT : + case IPP_TAG_NAME : + case IPP_TAG_KEYWORD : + case IPP_TAG_URI : + case IPP_TAG_URISCHEME : + case IPP_TAG_CHARSET : + case IPP_TAG_LANGUAGE : + case IPP_TAG_MIMETYPE : + dstattr = ippAddStrings(dst, srcattr->group_tag, + (ipp_tag_t)(srcattr->value_tag | quickcopy), + srcattr->name, srcattr->num_values, NULL, NULL); + if (!dstattr) + break; - ipp->current = NULL; - ipp->prev = NULL; + if (quickcopy) + { + for (i = srcattr->num_values, srcval = srcattr->values, + dstval = dstattr->values; + i > 0; + i --, srcval ++, dstval ++) + dstval->string.text = srcval->string.text; + } + else if (srcattr->value_tag & IPP_TAG_COPY) + { + for (i = srcattr->num_values, srcval = srcattr->values, + dstval = dstattr->values; + i > 0; + i --, srcval ++, dstval ++) + dstval->string.text = _cupsStrAlloc(srcval->string.text); + } + else + { + for (i = srcattr->num_values, srcval = srcattr->values, + dstval = dstattr->values; + i > 0; + i --, srcval ++, dstval ++) + dstval->string.text = _cupsStrRetain(srcval->string.text); + } + break; - return (NULL); -} + case IPP_TAG_DATE : + if (srcattr->num_values != 1) + return (NULL); + dstattr = ippAddDate(dst, srcattr->group_tag, srcattr->name, + srcattr->values[0].date); + break; -/* - * 'ippLength()' - Compute the length of an IPP message. - */ + case IPP_TAG_RESOLUTION : + dstattr = ippAddResolutions(dst, srcattr->group_tag, srcattr->name, + srcattr->num_values, IPP_RES_PER_INCH, + NULL, NULL); + if (!dstattr) + break; + + for (i = srcattr->num_values, srcval = srcattr->values, dstval = dstattr->values; + i > 0; + i --, srcval ++, dstval ++) + { + dstval->resolution.xres = srcval->resolution.xres; + dstval->resolution.yres = srcval->resolution.yres; + dstval->resolution.units = srcval->resolution.units; + } + break; -size_t /* O - Size of IPP message */ -ippLength(ipp_t *ipp) /* I - IPP message */ -{ - return (ipp_length(ipp, 0)); -} + case IPP_TAG_RANGE : + dstattr = ippAddRanges(dst, srcattr->group_tag, srcattr->name, + srcattr->num_values, NULL, NULL); + if (!dstattr) + break; + + for (i = srcattr->num_values, srcval = srcattr->values, dstval = dstattr->values; + i > 0; + i --, srcval ++, dstval ++) + { + dstval->range.lower = srcval->range.lower; + dstval->range.upper = srcval->range.upper; + } + break; + case IPP_TAG_TEXTLANG : + case IPP_TAG_NAMELANG : + dstattr = ippAddStrings(dst, srcattr->group_tag, + (ipp_tag_t)(srcattr->value_tag | quickcopy), + srcattr->name, srcattr->num_values, NULL, NULL); + if (!dstattr) + break; -/* - * 'ippNew()' - Allocate a new IPP message. - */ + if (quickcopy) + { + for (i = srcattr->num_values, srcval = srcattr->values, + dstval = dstattr->values; + i > 0; + i --, srcval ++, dstval ++) + { + dstval->string.language = srcval->string.language; + dstval->string.text = srcval->string.text; + } + } + else if (srcattr->value_tag & IPP_TAG_COPY) + { + for (i = srcattr->num_values, srcval = srcattr->values, + dstval = dstattr->values; + i > 0; + i --, srcval ++, dstval ++) + { + if (srcval == srcattr->values) + dstval->string.language = _cupsStrAlloc(srcval->string.language); + else + dstval->string.language = dstattr->values[0].string.language; -ipp_t * /* O - New IPP message */ -ippNew(void) -{ - ipp_t *temp; /* New IPP message */ + dstval->string.text = _cupsStrAlloc(srcval->string.text); + } + } + else + { + for (i = srcattr->num_values, srcval = srcattr->values, + dstval = dstattr->values; + i > 0; + i --, srcval ++, dstval ++) + { + if (srcval == srcattr->values) + dstval->string.language = _cupsStrRetain(srcval->string.language); + else + dstval->string.language = dstattr->values[0].string.language; + dstval->string.text = _cupsStrRetain(srcval->string.text); + } + } + break; - DEBUG_puts("ippNew()"); + case IPP_TAG_BEGIN_COLLECTION : + dstattr = ippAddCollections(dst, srcattr->group_tag, srcattr->name, + srcattr->num_values, NULL); + if (!dstattr) + break; + + for (i = srcattr->num_values, srcval = srcattr->values, dstval = dstattr->values; + i > 0; + i --, srcval ++, dstval ++) + { + dstval->collection = srcval->collection; + srcval->collection->use ++; + } + break; - if ((temp = (ipp_t *)calloc(1, sizeof(ipp_t))) != NULL) - { - /* - * Default to IPP 1.1... - */ + case IPP_TAG_STRING : + default : + /* TODO: Implement quick copy for unknown/octetString values */ + dstattr = ippAddIntegers(dst, srcattr->group_tag, srcattr->value_tag, + srcattr->name, srcattr->num_values, NULL); + if (!dstattr) + break; + + for (i = srcattr->num_values, srcval = srcattr->values, dstval = dstattr->values; + i > 0; + i --, srcval ++, dstval ++) + { + dstval->unknown.length = srcval->unknown.length; - temp->request.any.version[0] = 1; - temp->request.any.version[1] = 1; - temp->use = 1; + if (dstval->unknown.length > 0) + { + if ((dstval->unknown.data = malloc(dstval->unknown.length)) == NULL) + dstval->unknown.length = 0; + else + memcpy(dstval->unknown.data, srcval->unknown.data, dstval->unknown.length); + } + } + break; /* anti-compiler-warning-code */ } - DEBUG_printf(("1ippNew: Returning %p", temp)); - - return (temp); + return (dstattr); } /* - * 'ippNewRequest()' - Allocate a new IPP request message. + * 'ippCopyAttributes()' - Copy attributes from one IPP message to another. * - * The new request message is initialized with the attributes-charset and - * attributes-natural-language attributes added. The - * attributes-natural-language value is derived from the current locale. + * Zero or more attributes are copied from the source IPP message, @code@ src, to the + * destination IPP message, @code dst@. When @code quickcopy@ is non-zero, a "shallow" + * reference copy of the attribute is created - this should only be done as long as the + * original source IPP message will not be freed for the life of the destination. * - * @since CUPS 1.2/Mac OS X 10.5@ + * The @code cb@ and @code context@ parameters provide a generic way to "filter" the + * attributes that are copied - the function must return 1 to copy the attribute or + * 0 to skip it. The function may also choose to do a partial copy of the source attribute + * itself. + * + * @since CUPS 1.6@ */ -ipp_t * /* O - IPP request message */ -ippNewRequest(ipp_op_t op) /* I - Operation code */ +int /* O - 1 on success, 0 on error */ +ippCopyAttributes( + ipp_t *dst, /* I - Destination IPP message */ + ipp_t *src, /* I - Source IPP message */ + int quickcopy, /* I - 1 for a referenced copy, 0 for normal */ + ipp_copycb_t cb, /* I - Copy callback or @code NULL@ for none */ + void *context) /* I - Context pointer */ { - ipp_t *request; /* IPP request message */ - cups_lang_t *language; /* Current language localization */ + ipp_attribute_t *srcattr; /* Source attribute */ - DEBUG_printf(("ippNewRequest(op=%02x(%s))", op, ippOpString(op))); + DEBUG_printf(("ippCopyAttributes(dst=%p, src=%p, quickcopy=%d, cb=%p, context=%p)", + dst, src, quickcopy, cb, context)); /* - * Create a new IPP message... + * Range check input... */ - if ((request = ippNew()) == NULL) - return (NULL); + if (!dst || !src) + return (0); /* - * Set the operation and request ID... + * Loop through source attributes and copy as needed... */ - request->request.op.operation_id = op; - request->request.op.request_id = 1; + for (srcattr = src->attrs; srcattr; srcattr = srcattr->next) + if (!cb || (*cb)(context, dst, srcattr)) + if (!ippCopyAttribute(dst, srcattr, quickcopy)) + return (0); - /* - * Use UTF-8 as the character set... - */ + return (1); +} - ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET, - "attributes-charset", NULL, "utf-8"); - /* - * Get the language from the current locale... - */ +/* + * 'ippDateToTime()' - Convert from RFC 1903 Date/Time format to UNIX time + * in seconds. + */ - language = cupsLangDefault(); +time_t /* O - UNIX time value */ +ippDateToTime(const ipp_uchar_t *date) /* I - RFC 1903 date info */ +{ + struct tm unixdate; /* UNIX date/time info */ + time_t t; /* Computed time */ - ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE, - "attributes-natural-language", NULL, language->language); + + if (!date) + return (0); + + memset(&unixdate, 0, sizeof(unixdate)); /* - * Return the new request... + * RFC-1903 date/time format is: + * + * Byte(s) Description + * ------- ----------- + * 0-1 Year (0 to 65535) + * 2 Month (1 to 12) + * 3 Day (1 to 31) + * 4 Hours (0 to 23) + * 5 Minutes (0 to 59) + * 6 Seconds (0 to 60, 60 = "leap second") + * 7 Deciseconds (0 to 9) + * 8 +/- UTC + * 9 UTC hours (0 to 11) + * 10 UTC minutes (0 to 59) */ - return (request); + unixdate.tm_year = ((date[0] << 8) | date[1]) - 1900; + unixdate.tm_mon = date[2] - 1; + unixdate.tm_mday = date[3]; + unixdate.tm_hour = date[4]; + unixdate.tm_min = date[5]; + unixdate.tm_sec = date[6]; + + t = mktime(&unixdate); + + if (date[8] == '-') + t += date[9] * 3600 + date[10] * 60; + else + t -= date[9] * 3600 + date[10] * 60; + + return (t); } /* - * 'ippRead()' - Read data for an IPP message from a HTTP connection. + * 'ippDelete()' - Delete an IPP message. */ -ipp_state_t /* O - Current state */ -ippRead(http_t *http, /* I - HTTP connection */ - ipp_t *ipp) /* I - IPP data */ +void +ippDelete(ipp_t *ipp) /* I - IPP message */ { - DEBUG_printf(("ippRead(http=%p, ipp=%p), data_remaining=" CUPS_LLFMT, - http, ipp, CUPS_LLCAST (http ? http->data_remaining : -1))); + ipp_attribute_t *attr, /* Current attribute */ + *next; /* Next attribute */ - if (!http) - return (IPP_ERROR); - DEBUG_printf(("2ippRead: http->state=%d, http->used=%d", http->state, - http->used)); + DEBUG_printf(("ippDelete(ipp=%p)", ipp)); - return (ippReadIO(http, (ipp_iocb_t)ipp_read_http, http->blocking, NULL, - ipp)); -} + if (!ipp) + return; + + ipp->use --; + if (ipp->use > 0) + return; + for (attr = ipp->attrs; attr != NULL; attr = next) + { + next = attr->next; -/* - * 'ippReadFile()' - Read data for an IPP message from a file. - * - * @since CUPS 1.1.19/Mac OS X 10.3@ - */ + ipp_free_values(attr, 0, attr->num_values); -ipp_state_t /* O - Current state */ -ippReadFile(int fd, /* I - HTTP data */ - ipp_t *ipp) /* I - IPP data */ -{ - DEBUG_printf(("ippReadFile(fd=%d, ipp=%p)", fd, ipp)); + if (attr->name) + _cupsStrFree(attr->name); - return (ippReadIO(&fd, (ipp_iocb_t)ipp_read_file, 1, NULL, ipp)); + free(attr); + } + + free(ipp); } /* - * 'ippReadIO()' - Read data for an IPP message. + * 'ippDeleteAttribute()' - Delete a single attribute in an IPP message. * - * @since CUPS 1.2/Mac OS X 10.5@ + * @since CUPS 1.1.19/Mac OS X 10.3@ */ -ipp_state_t /* O - Current state */ -ippReadIO(void *src, /* I - Data source */ - ipp_iocb_t cb, /* I - Read callback function */ - int blocking, /* I - Use blocking IO? */ - ipp_t *parent, /* I - Parent request, if any */ - ipp_t *ipp) /* I - IPP data */ +void +ippDeleteAttribute( + ipp_t *ipp, /* I - IPP message */ + ipp_attribute_t *attr) /* I - Attribute to delete */ { - int n; /* Length of data */ - unsigned char *buffer, /* Data buffer */ - string[IPP_MAX_NAME], - /* Small string buffer */ - *bufptr; /* Pointer into buffer */ - ipp_attribute_t *attr; /* Current attribute */ - ipp_tag_t tag; /* Current tag */ - ipp_tag_t value_tag; /* Current value tag */ - ipp_value_t *value; /* Current value */ + ipp_attribute_t *current, /* Current attribute */ + *prev; /* Previous attribute */ - DEBUG_printf(("ippReadIO(src=%p, cb=%p, blocking=%d, parent=%p, ipp=%p)", - src, cb, blocking, parent, ipp)); - DEBUG_printf(("2ippReadIO: ipp->state=%d", ipp->state)); + DEBUG_printf(("ippDeleteAttribute(ipp=%p, attr=%p(%s))", ipp, attr, + attr ? attr->name : "(null)")); - if (!src || !ipp) - return (IPP_ERROR); + /* + * Range check input... + */ - if ((buffer = ipp_buffer_get()) == NULL) - { - DEBUG_puts("1ippReadIO: Unable to get read buffer."); - return (IPP_ERROR); - } + if (!attr) + return; - switch (ipp->state) + /* + * Find the attribute in the list... + */ + + if (ipp) { - case IPP_IDLE : - ipp->state ++; /* Avoid common problem... */ + for (current = ipp->attrs, prev = NULL; + current; + prev = current, current = current->next) + if (current == attr) + { + /* + * Found it, remove the attribute from the list... + */ - case IPP_HEADER : - if (parent == NULL) - { - /* - * Get the request header... - */ + if (prev) + prev->next = current->next; + else + ipp->attrs = current->next; - if ((*cb)(src, buffer, 8) < 8) - { - DEBUG_puts("1ippReadIO: Unable to read header."); - ipp_buffer_release(buffer); - return (IPP_ERROR); - } + if (current == ipp->last) + ipp->last = prev; - /* - * Then copy the request header over... - */ + break; + } - ipp->request.any.version[0] = buffer[0]; - ipp->request.any.version[1] = buffer[1]; - ipp->request.any.op_status = (buffer[2] << 8) | buffer[3]; - ipp->request.any.request_id = (((((buffer[4] << 8) | buffer[5]) << 8) | - buffer[6]) << 8) | buffer[7]; + if (!current) + return; + } - DEBUG_printf(("2ippReadIO: version=%d.%d", buffer[0], buffer[1])); - DEBUG_printf(("2ippReadIO: op_status=%04x", - ipp->request.any.op_status)); - DEBUG_printf(("2ippReadIO: request_id=%d", - ipp->request.any.request_id)); - } + /* + * Free memory used by the attribute... + */ - ipp->state = IPP_ATTRIBUTE; - ipp->current = NULL; - ipp->curtag = IPP_TAG_ZERO; - ipp->prev = ipp->last; + ipp_free_values(attr, 0, attr->num_values); - /* - * If blocking is disabled, stop here... - */ + if (attr->name) + _cupsStrFree(attr->name); - if (!blocking) - break; + free(attr); +} - case IPP_ATTRIBUTE : - for (;;) - { - if ((*cb)(src, buffer, 1) < 1) - { - DEBUG_puts("1ippReadIO: Callback returned EOF/error"); - ipp_buffer_release(buffer); - return (IPP_ERROR); - } - DEBUG_printf(("2ippReadIO: ipp->current=%p, ipp->prev=%p", - ipp->current, ipp->prev)); +/* + * 'ippDeleteValues()' - Delete values in an attribute. + * + * The @code element@ parameter specifies the first value to delete, starting at 0. It + * must be less than the number of values returned by @link ippGetCount@. + * + * Deleting all values in an attribute deletes the attribute. + * + * @since CUPS 1.6@ + */ - /* - * Read this attribute... - */ +int /* O - 1 on success, 0 on failure */ +ippDeleteValues( + ipp_t *ipp, /* I - IPP message */ + ipp_attribute_t *attr, /* I - Attribute */ + int element, /* I - Index of first value to delete (0-based) */ + int count) /* I - Number of values to delete */ +{ + /* + * Range check input... + */ - tag = (ipp_tag_t)buffer[0]; + if (!ipp || !attr || element < 0 || element >= attr->num_values || count <= 0 || + (element + count) >= attr->num_values) + return (0); - if (tag == IPP_TAG_END) - { - /* - * No more attributes left... - */ + /* + * If we are deleting all values, just delete the attribute entirely. + */ - DEBUG_puts("2ippReadIO: IPP_TAG_END."); + if (count == attr->num_values) + { + ippDeleteAttribute(ipp, attr); + return (1); + } - ipp->state = IPP_DATA; - break; - } - else if (tag < IPP_TAG_UNSUPPORTED_VALUE) - { - /* - * Group tag... Set the current group and continue... - */ + /* + * Otherwise free the values in question and return. + */ - if (ipp->curtag == tag) - ipp->prev = ippAddSeparator(ipp); - else if (ipp->current) - ipp->prev = ipp->current; + ipp_free_values(attr, element, count); + + return (1); +} + + +/* + * 'ippFindAttribute()' - Find a named attribute in a request... + */ + +ipp_attribute_t * /* O - Matching attribute */ +ippFindAttribute(ipp_t *ipp, /* I - IPP message */ + const char *name, /* I - Name of attribute */ + ipp_tag_t type) /* I - Type of attribute */ +{ + DEBUG_printf(("2ippFindAttribute(ipp=%p, name=\"%s\", type=%02x(%s))", ipp, + name, type, ippTagString(type))); + + if (!ipp || !name) + return (NULL); + + /* + * Reset the current pointer... + */ + + ipp->current = NULL; + + /* + * Search for the attribute... + */ + + return (ippFindNextAttribute(ipp, name, type)); +} + + +/* + * 'ippFindNextAttribute()' - Find the next named attribute in a request... + */ + +ipp_attribute_t * /* O - Matching attribute */ +ippFindNextAttribute(ipp_t *ipp, /* I - IPP message */ + const char *name, /* I - Name of attribute */ + ipp_tag_t type) /* I - Type of attribute */ +{ + ipp_attribute_t *attr; /* Current atttribute */ + ipp_tag_t value_tag; /* Value tag */ + + + DEBUG_printf(("2ippFindNextAttribute(ipp=%p, name=\"%s\", type=%02x(%s))", + ipp, name, type, ippTagString(type))); + + if (!ipp || !name) + return (NULL); + + if (ipp->current) + { + ipp->prev = ipp->current; + attr = ipp->current->next; + } + else + { + ipp->prev = NULL; + attr = ipp->attrs; + } + + for (; attr != NULL; ipp->prev = attr, attr = attr->next) + { + DEBUG_printf(("4ippFindAttribute: attr=%p, name=\"%s\"", attr, + attr->name)); + + value_tag = (ipp_tag_t)(attr->value_tag & IPP_TAG_MASK); + + if (attr->name != NULL && _cups_strcasecmp(attr->name, name) == 0 && + (value_tag == type || type == IPP_TAG_ZERO || + (value_tag == IPP_TAG_TEXTLANG && type == IPP_TAG_TEXT) || + (value_tag == IPP_TAG_NAMELANG && type == IPP_TAG_NAME))) + { + ipp->current = attr; + + return (attr); + } + } + + ipp->current = NULL; + ipp->prev = NULL; + + return (NULL); +} + + +/* + * 'ippFirstAttribute()' - Return the first attribute in the message. + * + * @since CUPS 1.6@ + */ + +ipp_attribute_t * /* O - First attribute or @code NULL@ if none */ +ippFirstAttribute(ipp_t *ipp) /* I - IPP message */ +{ + /* + * Range check input... + */ + + if (!ipp) + return (NULL); + + /* + * Return the first attribute... + */ + + return (ipp->current = ipp->attrs); +} + + +/* + * 'ippGetBoolean()' - Get a boolean value for an attribute. + * + * The @code element@ parameter specifies which value to get from 0 to + * @link ippGetCount(attr)@ - 1. + * + * @since CUPS 1.6@ + */ + +int /* O - Boolean value or -1 on error */ +ippGetBoolean(ipp_attribute_t *attr, /* I - IPP attribute */ + int element) /* I - Value number (0-based) */ +{ + /* + * Range check input... + */ + + if (!attr || attr->value_tag != IPP_TAG_BOOLEAN || + element < 0 || element >= attr->num_values) + return (-1); + + /* + * Return the value... + */ + + return (attr->values[element].boolean); +} + + +/* + * 'ippGetCollection()' - Get a collection value for an attribute. + * + * The @code element@ parameter specifies which value to get from 0 to + * @link ippGetCount(attr)@ - 1. + * + * @since CUPS 1.6@ + */ + +ipp_t * /* O - Collection value or @code NULL@ on error */ +ippGetCollection( + ipp_attribute_t *attr, /* I - IPP attribute */ + int element) /* I - Value number (0-based) */ +{ + /* + * Range check input... + */ + + if (!attr || attr->value_tag != IPP_TAG_BEGIN_COLLECTION || + element < 0 || element >= attr->num_values) + return (NULL); + + /* + * Return the value... + */ + + return (attr->values[element].collection); +} + + +/* + * 'ippGetCount()' - Get the number of values in an attribute. + * + * @since CUPS 1.6@ + */ + +int /* O - Number of values or -1 on error */ +ippGetCount(ipp_attribute_t *attr) /* I - IPP attribute */ +{ + /* + * Range check input... + */ + + if (!attr) + return (-1); + + /* + * Return the number of values... + */ + + return (attr->num_values); +} + + +/* + * 'ippGetGroupTag()' - Get the group associated with an attribute. + * + * @since CUPS 1.6@ + */ + +ipp_tag_t /* O - Group tag or @code IPP_TAG_ZERO@ on error */ +ippGetGroupTag(ipp_attribute_t *attr) /* I - IPP attribute */ +{ + /* + * Range check input... + */ + + if (!attr) + return (IPP_TAG_ZERO); + + /* + * Return the group... + */ + + return (attr->group_tag); +} + + +/* + * 'ippGetInteger()' - Get the integer/enum value for an attribute. + * + * The @code element@ parameter specifies which value to get from 0 to + * @link ippGetCount(attr)@ - 1. + * + * @since CUPS 1.6@ + */ + +int /* O - Value or -1 on error */ +ippGetInteger(ipp_attribute_t *attr, /* I - IPP attribute */ + int element) /* I - Value number (0-based) */ +{ + /* + * Range check input... + */ + + if (!attr || (attr->value_tag != IPP_TAG_INTEGER && attr->value_tag != IPP_TAG_ENUM) || + element < 0 || element >= attr->num_values) + return (-1); + + /* + * Return the value... + */ + + return (attr->values[element].integer); +} + + +/* + * 'ippGetName()' - Get the attribute name. + * + * @since CUPS 1.6@ + */ + +const char * /* O - Attribute name or @code NULL@ for separators */ +ippGetName(ipp_attribute_t *attr) /* I - IPP attribute */ +{ + /* + * Range check input... + */ + + if (!attr) + return (NULL); + + /* + * Return the name... + */ + + return (attr->name); +} + + +/* + * 'ippGetOperation()' - Get the operation ID in an IPP message. + * + * @since CUPS 1.6@ + */ + +ipp_op_t /* O - Operation ID or -1 on error */ +ippGetOperation(ipp_t *ipp) /* I - IPP request message */ +{ + /* + * Range check input... + */ + + if (!ipp) + return ((ipp_op_t)-1); + + /* + * Return the value... + */ + + return (ipp->request.op.operation_id); +} + + +/* + * 'ippGetRequestId()' - Get the request ID from an IPP message. + * + * @since CUPS 1.6@ + */ + +int /* O - Request ID or -1 on error */ +ippGetRequestId(ipp_t *ipp) /* I - IPP message */ +{ + /* + * Range check input... + */ + + if (!ipp) + return (-1); + + /* + * Return the request ID... + */ + + return (ipp->request.any.request_id); +} + + +/* + * 'ippGetResolution()' - Get a resolution value for an attribute. + * + * The @code element@ parameter specifies which value to get from 0 to + * @link ippGetCount(attr)@ - 1. + * + * @since CUPS 1.6@ + */ + +int /* O - Horizontal/cross feed resolution or -1 */ +ippGetResolution( + ipp_attribute_t *attr, /* I - IPP attribute */ + int element, /* I - Value number (0-based) */ + int *yres, /* O - Vertical/feed resolution */ + ipp_res_t *units) /* O - Units for resolution */ +{ + /* + * Range check input... + */ + + if (!attr || attr->value_tag != IPP_TAG_RESOLUTION || + element < 0 || element >= attr->num_values) + return (-1); + + /* + * Return the value... + */ + + if (yres) + *yres = attr->values[element].resolution.yres; + + if (units) + *units = attr->values[element].resolution.units; + + return (attr->values[element].resolution.xres); +} + + +/* + * 'ippGetStatusCode()' - Get the status code from an IPP response or event message. + * + * @since CUPS 1.6@ + */ + +ipp_status_t /* O - Status code in IPP message */ +ippGetStatusCode(ipp_t *ipp) /* I - IPP response or event message */ +{ + /* + * Range check input... + */ + + if (!ipp) + return (IPP_INTERNAL_ERROR); + + /* + * Return the value... + */ + + return (ipp->request.status.status_code); +} + + +/* + * 'ippGetString()' - Get the string and optionally the language code for an attribute. + * + * The @code element@ parameter specifies which value to get from 0 to + * @link ippGetCount(attr)@ - 1. + * + * @since CUPS 1.6@ + */ + +const char * +ippGetString(ipp_attribute_t *attr, /* I - IPP attribute */ + int element, /* I - Value number (0-based) */ + const char **language)/* O - Language code (@code NULL@ for don't care) */ +{ + /* + * Range check input... + */ + + if (!attr || element < 0 || element >= attr->num_values || + (attr->value_tag != IPP_TAG_TEXTLANG && attr->value_tag != IPP_TAG_NAMELANG && + (attr->value_tag < IPP_TAG_TEXT || attr->value_tag > IPP_TAG_MIMETYPE))) + return (NULL); + + /* + * Return the value... + */ + + if (language) + *language = attr->values[element].string.language; + + return (attr->values[element].string.text); +} + + +/* + * 'ippGetValueTag()' - Get the value tag for an attribute. + * + * @since CUPS 1.6@ + */ + +ipp_tag_t /* O - Value tag or @code IPP_TAG_ZERO@ on error */ +ippGetValueTag(ipp_attribute_t *attr) /* I - IPP attribute */ +{ + /* + * Range check input... + */ + + if (!attr) + return (IPP_TAG_ZERO); + + /* + * Return the value... + */ + + return (attr->value_tag); +} + + +/* + * 'ippGetVersion()' - Get the major and minor version number from an IPP message. + * + * @since CUPS 1.6@ + */ + +int /* O - Major version number or -1 on error */ +ippGetVersion(ipp_t *ipp, /* I - IPP message */ + int *minor) /* O - Minor version number or @code NULL@ */ +{ + /* + * Range check input... + */ + + if (!ipp) + { + if (minor) + *minor = -1; + + return (-1); + } + + /* + * Return the value... + */ + + if (minor) + *minor = ipp->request.any.version[1]; + + return (ipp->request.any.version[0]); +} + + +/* + * 'ippLength()' - Compute the length of an IPP message. + */ + +size_t /* O - Size of IPP message */ +ippLength(ipp_t *ipp) /* I - IPP message */ +{ + return (ipp_length(ipp, 0)); +} + + +/* + * 'ippNextAttribute()' - Return the next attribute in the message. + * + * @since CUPS 1.6@ + */ + +ipp_attribute_t * /* O - Next attribute or @code NULL@ if none */ +ippNextAttribute(ipp_t *ipp) /* I - IPP message */ +{ + /* + * Range check input... + */ + + if (!ipp || !ipp->current) + return (NULL); + + /* + * Return the next attribute... + */ + + return (ipp->current = ipp->current->next); +} + + +/* + * 'ippNew()' - Allocate a new IPP message. + */ + +ipp_t * /* O - New IPP message */ +ippNew(void) +{ + ipp_t *temp; /* New IPP message */ + + + DEBUG_puts("ippNew()"); + + if ((temp = (ipp_t *)calloc(1, sizeof(ipp_t))) != NULL) + { + /* + * Default to IPP 2.0... + */ + + temp->request.any.version[0] = 2; + temp->request.any.version[1] = 0; + temp->use = 1; + } + + DEBUG_printf(("1ippNew: Returning %p", temp)); + + return (temp); +} + + +/* + * 'ippNewRequest()' - Allocate a new IPP request message. + * + * The new request message is initialized with the attributes-charset and + * attributes-natural-language attributes added. The + * attributes-natural-language value is derived from the current locale. + * + * @since CUPS 1.2/Mac OS X 10.5@ + */ + +ipp_t * /* O - IPP request message */ +ippNewRequest(ipp_op_t op) /* I - Operation code */ +{ + ipp_t *request; /* IPP request message */ + cups_lang_t *language; /* Current language localization */ + static int request_id = 0; /* Current request ID */ + static _cups_mutex_t request_mutex = _CUPS_MUTEX_INITIALIZER; + /* Mutex for request ID */ + + + DEBUG_printf(("ippNewRequest(op=%02x(%s))", op, ippOpString(op))); + + /* + * Create a new IPP message... + */ + + if ((request = ippNew()) == NULL) + return (NULL); + + /* + * Set the operation and request ID... + */ + + _cupsMutexLock(&request_mutex); + + request->request.op.operation_id = op; + request->request.op.request_id = ++request_id; + + _cupsMutexUnlock(&request_mutex); + + /* + * Use UTF-8 as the character set... + */ + + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET, + "attributes-charset", NULL, "utf-8"); + + /* + * Get the language from the current locale... + */ + + language = cupsLangDefault(); + + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE, + "attributes-natural-language", NULL, language->language); + + /* + * Return the new request... + */ + + return (request); +} + + +/* + * 'ippRead()' - Read data for an IPP message from a HTTP connection. + */ + +ipp_state_t /* O - Current state */ +ippRead(http_t *http, /* I - HTTP connection */ + ipp_t *ipp) /* I - IPP data */ +{ + DEBUG_printf(("ippRead(http=%p, ipp=%p), data_remaining=" CUPS_LLFMT, + http, ipp, CUPS_LLCAST (http ? http->data_remaining : -1))); + + if (!http) + return (IPP_ERROR); + + DEBUG_printf(("2ippRead: http->state=%d, http->used=%d", http->state, + http->used)); + + return (ippReadIO(http, (ipp_iocb_t)ipp_read_http, http->blocking, NULL, + ipp)); +} + + +/* + * 'ippReadFile()' - Read data for an IPP message from a file. + * + * @since CUPS 1.1.19/Mac OS X 10.3@ + */ + +ipp_state_t /* O - Current state */ +ippReadFile(int fd, /* I - HTTP data */ + ipp_t *ipp) /* I - IPP data */ +{ + DEBUG_printf(("ippReadFile(fd=%d, ipp=%p)", fd, ipp)); + + return (ippReadIO(&fd, (ipp_iocb_t)ipp_read_file, 1, NULL, ipp)); +} + + +/* + * 'ippReadIO()' - Read data for an IPP message. + * + * @since CUPS 1.2/Mac OS X 10.5@ + */ + +ipp_state_t /* O - Current state */ +ippReadIO(void *src, /* I - Data source */ + ipp_iocb_t cb, /* I - Read callback function */ + int blocking, /* I - Use blocking IO? */ + ipp_t *parent, /* I - Parent request, if any */ + ipp_t *ipp) /* I - IPP data */ +{ + int n; /* Length of data */ + unsigned char *buffer, /* Data buffer */ + string[IPP_MAX_NAME], + /* Small string buffer */ + *bufptr; /* Pointer into buffer */ + ipp_attribute_t *attr; /* Current attribute */ + ipp_tag_t tag; /* Current tag */ + ipp_tag_t value_tag; /* Current value tag */ + _ipp_value_t *value; /* Current value */ + + + DEBUG_printf(("ippReadIO(src=%p, cb=%p, blocking=%d, parent=%p, ipp=%p)", + src, cb, blocking, parent, ipp)); + DEBUG_printf(("2ippReadIO: ipp->state=%d", ipp->state)); + + if (!src || !ipp) + return (IPP_ERROR); + + if ((buffer = ipp_buffer_get()) == NULL) + { + DEBUG_puts("1ippReadIO: Unable to get read buffer."); + return (IPP_ERROR); + } + + switch (ipp->state) + { + case IPP_IDLE : + ipp->state ++; /* Avoid common problem... */ + + case IPP_HEADER : + if (parent == NULL) + { + /* + * Get the request header... + */ + + if ((*cb)(src, buffer, 8) < 8) + { + DEBUG_puts("1ippReadIO: Unable to read header."); + ipp_buffer_release(buffer); + return (IPP_ERROR); + } + + /* + * Then copy the request header over... + */ + + ipp->request.any.version[0] = buffer[0]; + ipp->request.any.version[1] = buffer[1]; + ipp->request.any.op_status = (buffer[2] << 8) | buffer[3]; + ipp->request.any.request_id = (((((buffer[4] << 8) | buffer[5]) << 8) | + buffer[6]) << 8) | buffer[7]; + + DEBUG_printf(("2ippReadIO: version=%d.%d", buffer[0], buffer[1])); + DEBUG_printf(("2ippReadIO: op_status=%04x", + ipp->request.any.op_status)); + DEBUG_printf(("2ippReadIO: request_id=%d", + ipp->request.any.request_id)); + } + + ipp->state = IPP_ATTRIBUTE; + ipp->current = NULL; + ipp->curtag = IPP_TAG_ZERO; + ipp->prev = ipp->last; + + /* + * If blocking is disabled, stop here... + */ + + if (!blocking) + break; + + case IPP_ATTRIBUTE : + for (;;) + { + if ((*cb)(src, buffer, 1) < 1) + { + DEBUG_puts("1ippReadIO: Callback returned EOF/error"); + ipp_buffer_release(buffer); + return (IPP_ERROR); + } + + DEBUG_printf(("2ippReadIO: ipp->current=%p, ipp->prev=%p", + ipp->current, ipp->prev)); + + /* + * Read this attribute... + */ + + tag = (ipp_tag_t)buffer[0]; + if (tag == IPP_TAG_EXTENSION) + { + /* + * Read 32-bit "extension" tag... + */ + + if ((*cb)(src, buffer, 4) < 1) + { + DEBUG_puts("1ippReadIO: Callback returned EOF/error"); + ipp_buffer_release(buffer); + return (IPP_ERROR); + } + + tag = (ipp_tag_t)((((((buffer[0] << 8) | buffer[1]) << 8) | + buffer[2]) << 8) | buffer[3]); + + if (tag & IPP_TAG_COPY) + { + /* + * Fail if the high bit is set in the tag... + */ + + _cupsSetError(IPP_ERROR, _("IPP extension tag larger than 0x7FFFFFFF."), 1); + DEBUG_printf(("1ippReadIO: bad name length %d.", n)); + ipp_buffer_release(buffer); + return (IPP_ERROR); + } + } + + if (tag == IPP_TAG_END) + { + /* + * No more attributes left... + */ + + DEBUG_puts("2ippReadIO: IPP_TAG_END."); + + ipp->state = IPP_DATA; + break; + } + else if (tag < IPP_TAG_UNSUPPORTED_VALUE) + { + /* + * Group tag... Set the current group and continue... + */ + + if (ipp->curtag == tag) + ipp->prev = ippAddSeparator(ipp); + else if (ipp->current) + ipp->prev = ipp->current; ipp->curtag = tag; ipp->current = NULL; @@ -1216,617 +2453,1242 @@ ippReadIO(void *src, /* I - Data source */ continue; } - DEBUG_printf(("2ippReadIO: value tag=%x(%s)", tag, - ippTagString(tag))); + DEBUG_printf(("2ippReadIO: value tag=%x(%s)", tag, + ippTagString(tag))); + + /* + * Get the name... + */ + + if ((*cb)(src, buffer, 2) < 2) + { + DEBUG_puts("1ippReadIO: unable to read name length."); + ipp_buffer_release(buffer); + return (IPP_ERROR); + } + + n = (buffer[0] << 8) | buffer[1]; + + if (n >= IPP_BUF_SIZE) + { + _cupsSetError(IPP_ERROR, _("IPP name larger than 32767 bytes."), 1); + DEBUG_printf(("1ippReadIO: bad name length %d.", n)); + ipp_buffer_release(buffer); + return (IPP_ERROR); + } + + DEBUG_printf(("2ippReadIO: name length=%d", n)); + + if (n == 0 && tag != IPP_TAG_MEMBERNAME && + tag != IPP_TAG_END_COLLECTION) + { + /* + * More values for current attribute... + */ + + if (ipp->current == NULL) + { + _cupsSetError(IPP_ERROR, _("IPP attribute has no name."), 1); + DEBUG_puts("1ippReadIO: Attribute without name and no current."); + ipp_buffer_release(buffer); + return (IPP_ERROR); + } + + attr = ipp->current; + value_tag = (ipp_tag_t)(attr->value_tag & IPP_TAG_MASK); + + /* + * Make sure we aren't adding a new value of a different + * type... + */ + + if (value_tag == IPP_TAG_ZERO) + { + /* + * Setting the value of a collection member... + */ + + attr->value_tag = tag; + } + else if (value_tag == IPP_TAG_TEXTLANG || + value_tag == IPP_TAG_NAMELANG || + (value_tag >= IPP_TAG_TEXT && + value_tag <= IPP_TAG_MIMETYPE)) + { + /* + * String values can sometimes come across in different + * forms; accept sets of differing values... + */ + + if (tag != IPP_TAG_TEXTLANG && tag != IPP_TAG_NAMELANG && + (tag < IPP_TAG_TEXT || tag > IPP_TAG_MIMETYPE) && + tag != IPP_TAG_NOVALUE) + { + _cupsSetError(IPP_ERROR, + _("IPP 1setOf attribute with incompatible value " + "tags."), 1); + DEBUG_printf(("1ippReadIO: 1setOf value tag %x(%s) != %x(%s)", + value_tag, ippTagString(value_tag), tag, + ippTagString(tag))); + ipp_buffer_release(buffer); + return (IPP_ERROR); + } + + if (value_tag != tag) + { + DEBUG_printf(("1ippReadIO: Converting %s attribute from %s to %s.", + attr->name, ippTagString(value_tag), ippTagString(tag))); + ippSetValueTag(ipp, &attr, tag); + } + } + else if (value_tag == IPP_TAG_INTEGER || + value_tag == IPP_TAG_RANGE) + { + /* + * Integer and rangeOfInteger values can sometimes be mixed; accept + * sets of differing values... + */ + + if (tag != IPP_TAG_INTEGER && tag != IPP_TAG_RANGE) + { + _cupsSetError(IPP_ERROR, + _("IPP 1setOf attribute with incompatible value " + "tags."), 1); + DEBUG_printf(("1ippReadIO: 1setOf value tag %x(%s) != %x(%s)", + value_tag, ippTagString(value_tag), tag, + ippTagString(tag))); + ipp_buffer_release(buffer); + return (IPP_ERROR); + } + + if (value_tag == IPP_TAG_INTEGER && tag == IPP_TAG_RANGE) + { + /* + * Convert integer values to rangeOfInteger values... + */ + + DEBUG_printf(("1ippReadIO: Converting %s attribute to " + "rangeOfInteger.", attr->name)); + ippSetValueTag(ipp, &attr, IPP_TAG_RANGE); + } + } + else if (value_tag != tag) + { + _cupsSetError(IPP_ERROR, + _("IPP 1setOf attribute with incompatible value " + "tags."), 1); + DEBUG_printf(("1ippReadIO: value tag %x(%s) != %x(%s)", + value_tag, ippTagString(value_tag), tag, + ippTagString(tag))); + ipp_buffer_release(buffer); + return (IPP_ERROR); + } + + /* + * Finally, reallocate the attribute array as needed... + */ + + if ((value = ipp_set_value(ipp, &attr, attr->num_values)) == NULL) + { + ipp_buffer_release(buffer); + return (IPP_ERROR); + } + } + else if (tag == IPP_TAG_MEMBERNAME) + { + /* + * Name must be length 0! + */ + + if (n) + { + _cupsSetError(IPP_ERROR, _("IPP member name is not empty."), 1); + DEBUG_puts("1ippReadIO: member name not empty."); + ipp_buffer_release(buffer); + return (IPP_ERROR); + } + + if (ipp->current) + ipp->prev = ipp->current; + + attr = ipp->current = ipp_add_attr(ipp, NULL, ipp->curtag, IPP_TAG_ZERO, 1); + + DEBUG_printf(("2ippReadIO: membername, ipp->current=%p, ipp->prev=%p", + ipp->current, ipp->prev)); + + attr->num_values = 0; + value = attr->values; + } + else if (tag != IPP_TAG_END_COLLECTION) + { + /* + * New attribute; read the name and add it... + */ + + if ((*cb)(src, buffer, n) < n) + { + DEBUG_puts("1ippReadIO: unable to read name."); + ipp_buffer_release(buffer); + return (IPP_ERROR); + } + + buffer[n] = '\0'; + + if (ipp->current) + ipp->prev = ipp->current; + + if ((attr = ipp->current = ipp_add_attr(ipp, (char *)buffer, ipp->curtag, tag, + 1)) == NULL) + { + _cupsSetHTTPError(HTTP_ERROR); + DEBUG_puts("1ippReadIO: unable to allocate attribute."); + ipp_buffer_release(buffer); + return (IPP_ERROR); + } + + DEBUG_printf(("2ippReadIO: name=\"%s\", ipp->current=%p, " + "ipp->prev=%p", buffer, ipp->current, ipp->prev)); + + attr->num_values = 0; + value = attr->values; + } + else + { + attr = NULL; + value = NULL; + } + + if ((*cb)(src, buffer, 2) < 2) + { + DEBUG_puts("1ippReadIO: unable to read value length."); + ipp_buffer_release(buffer); + return (IPP_ERROR); + } + + n = (buffer[0] << 8) | buffer[1]; + DEBUG_printf(("2ippReadIO: value length=%d", n)); + + if (n >= IPP_BUF_SIZE) + { + _cupsSetError(IPP_ERROR, + _("IPP value larger than 32767 bytes."), 1); + DEBUG_printf(("1ippReadIO: bad value length %d.", n)); + ipp_buffer_release(buffer); + return (IPP_ERROR); + } + + switch (tag) + { + case IPP_TAG_INTEGER : + case IPP_TAG_ENUM : + if (n != 4) + { + if (tag == IPP_TAG_INTEGER) + _cupsSetError(IPP_ERROR, + _("IPP integer value not 4 bytes."), 1); + else + _cupsSetError(IPP_ERROR, + _("IPP enum value not 4 bytes."), 1); + DEBUG_printf(("1ippReadIO: bad value length %d.", n)); + ipp_buffer_release(buffer); + return (IPP_ERROR); + } + + if ((*cb)(src, buffer, 4) < 4) + { + DEBUG_puts("1ippReadIO: Unable to read integer value."); + ipp_buffer_release(buffer); + return (IPP_ERROR); + } + + n = (((((buffer[0] << 8) | buffer[1]) << 8) | buffer[2]) << 8) | + buffer[3]; + + if (attr->value_tag == IPP_TAG_RANGE) + value->range.lower = value->range.upper = n; + else + value->integer = n; + break; + + case IPP_TAG_BOOLEAN : + if (n != 1) + { + _cupsSetError(IPP_ERROR, _("IPP boolean value not 1 byte."), + 1); + DEBUG_printf(("1ippReadIO: bad value length %d.", n)); + ipp_buffer_release(buffer); + return (IPP_ERROR); + } + + if ((*cb)(src, buffer, 1) < 1) + { + DEBUG_puts("1ippReadIO: Unable to read boolean value."); + ipp_buffer_release(buffer); + return (IPP_ERROR); + } + + value->boolean = buffer[0]; + break; + + case IPP_TAG_NOVALUE : + case IPP_TAG_NOTSETTABLE : + case IPP_TAG_DELETEATTR : + case IPP_TAG_ADMINDEFINE : + /* + * These value types are not supposed to have values, however + * some vendors (Brother) do not implement IPP correctly and so + * we need to map non-empty values to text... + */ + + if (attr->value_tag == tag) + { + if (n == 0) + break; + + attr->value_tag = IPP_TAG_TEXT; + } + + case IPP_TAG_TEXT : + case IPP_TAG_NAME : + case IPP_TAG_KEYWORD : + case IPP_TAG_URI : + case IPP_TAG_URISCHEME : + case IPP_TAG_CHARSET : + case IPP_TAG_LANGUAGE : + case IPP_TAG_MIMETYPE : + if ((*cb)(src, buffer, n) < n) + { + DEBUG_puts("1ippReadIO: unable to read string value."); + ipp_buffer_release(buffer); + return (IPP_ERROR); + } + + buffer[n] = '\0'; + value->string.text = _cupsStrAlloc((char *)buffer); + DEBUG_printf(("2ippReadIO: value=\"%s\"", value->string.text)); + break; + + case IPP_TAG_DATE : + if (n != 11) + { + _cupsSetError(IPP_ERROR, _("IPP date value not 11 bytes."), 1); + DEBUG_printf(("1ippReadIO: bad value length %d.", n)); + ipp_buffer_release(buffer); + return (IPP_ERROR); + } + + if ((*cb)(src, value->date, 11) < 11) + { + DEBUG_puts("1ippReadIO: Unable to read date value."); + ipp_buffer_release(buffer); + return (IPP_ERROR); + } + break; + + case IPP_TAG_RESOLUTION : + if (n != 9) + { + _cupsSetError(IPP_ERROR, + _("IPP resolution value not 9 bytes."), 1); + DEBUG_printf(("1ippReadIO: bad value length %d.", n)); + ipp_buffer_release(buffer); + return (IPP_ERROR); + } + + if ((*cb)(src, buffer, 9) < 9) + { + DEBUG_puts("1ippReadIO: Unable to read resolution value."); + ipp_buffer_release(buffer); + return (IPP_ERROR); + } + + value->resolution.xres = + (((((buffer[0] << 8) | buffer[1]) << 8) | buffer[2]) << 8) | + buffer[3]; + value->resolution.yres = + (((((buffer[4] << 8) | buffer[5]) << 8) | buffer[6]) << 8) | + buffer[7]; + value->resolution.units = + (ipp_res_t)buffer[8]; + break; + + case IPP_TAG_RANGE : + if (n != 8) + { + _cupsSetError(IPP_ERROR, + _("IPP rangeOfInteger value not 8 bytes."), 1); + DEBUG_printf(("1ippReadIO: bad value length %d.", n)); + ipp_buffer_release(buffer); + return (IPP_ERROR); + } + + if ((*cb)(src, buffer, 8) < 8) + { + DEBUG_puts("1ippReadIO: Unable to read range value."); + ipp_buffer_release(buffer); + return (IPP_ERROR); + } + + value->range.lower = + (((((buffer[0] << 8) | buffer[1]) << 8) | buffer[2]) << 8) | + buffer[3]; + value->range.upper = + (((((buffer[4] << 8) | buffer[5]) << 8) | buffer[6]) << 8) | + buffer[7]; + break; + + case IPP_TAG_TEXTLANG : + case IPP_TAG_NAMELANG : + if (n < 4) + { + if (tag == IPP_TAG_TEXTLANG) + _cupsSetError(IPP_ERROR, + _("IPP textWithLanguage value less than " + "minimum 4 bytes."), 1); + else + _cupsSetError(IPP_ERROR, + _("IPP nameWithLanguage value less than " + "minimum 4 bytes."), 1); + DEBUG_printf(("1ippReadIO: bad value length %d.", n)); + ipp_buffer_release(buffer); + return (IPP_ERROR); + } + + if ((*cb)(src, buffer, n) < n) + { + DEBUG_puts("1ippReadIO: Unable to read string w/language " + "value."); + ipp_buffer_release(buffer); + return (IPP_ERROR); + } + + bufptr = buffer; + + /* + * text-with-language and name-with-language are composite + * values: + * + * language-length + * language + * text-length + * text + */ + + n = (bufptr[0] << 8) | bufptr[1]; + + if ((bufptr + 2 + n) >= (buffer + IPP_BUF_SIZE) || + n >= sizeof(string)) + { + _cupsSetError(IPP_ERROR, + _("IPP language length overflows value."), 1); + DEBUG_printf(("1ippReadIO: bad value length %d.", n)); + ipp_buffer_release(buffer); + return (IPP_ERROR); + } + + memcpy(string, bufptr + 2, n); + string[n] = '\0'; + + value->string.language = _cupsStrAlloc((char *)string); + + bufptr += 2 + n; + n = (bufptr[0] << 8) | bufptr[1]; + + if ((bufptr + 2 + n) >= (buffer + IPP_BUF_SIZE)) + { + _cupsSetError(IPP_ERROR, + _("IPP string length overflows value."), 1); + DEBUG_printf(("1ippReadIO: bad value length %d.", n)); + ipp_buffer_release(buffer); + return (IPP_ERROR); + } + + bufptr[2 + n] = '\0'; + value->string.text = _cupsStrAlloc((char *)bufptr + 2); + break; + + case IPP_TAG_BEGIN_COLLECTION : + /* + * Oh, boy, here comes a collection value, so read it... + */ + + value->collection = ippNew(); + + if (n > 0) + { + _cupsSetError(IPP_ERROR, + _("IPP begCollection value not 0 bytes."), 1); + DEBUG_puts("1ippReadIO: begCollection tag with value length " + "> 0."); + ipp_buffer_release(buffer); + return (IPP_ERROR); + } + + if (ippReadIO(src, cb, 1, ipp, value->collection) == IPP_ERROR) + { + DEBUG_puts("1ippReadIO: Unable to read collection value."); + ipp_buffer_release(buffer); + return (IPP_ERROR); + } + break; + + case IPP_TAG_END_COLLECTION : + ipp_buffer_release(buffer); + + if (n > 0) + { + _cupsSetError(IPP_ERROR, + _("IPP endCollection value not 0 bytes."), 1); + DEBUG_puts("1ippReadIO: endCollection tag with value length " + "> 0."); + return (IPP_ERROR); + } + + DEBUG_puts("1ippReadIO: endCollection tag..."); + return (ipp->state = IPP_DATA); + + case IPP_TAG_MEMBERNAME : + /* + * The value the name of the member in the collection, which + * we need to carry over... + */ + + if ((*cb)(src, buffer, n) < n) + { + DEBUG_puts("1ippReadIO: Unable to read member name value."); + ipp_buffer_release(buffer); + return (IPP_ERROR); + } + + buffer[n] = '\0'; + attr->name = _cupsStrAlloc((char *)buffer); + + /* + * Since collection members are encoded differently than + * regular attributes, make sure we don't start with an + * empty value... + */ + + attr->num_values --; + + DEBUG_printf(("2ippReadIO: member name=\"%s\"", attr->name)); + break; + + default : /* Other unsupported values */ + value->unknown.length = n; + if (n > 0) + { + if ((value->unknown.data = malloc(n)) == NULL) + { + _cupsSetHTTPError(HTTP_ERROR); + DEBUG_puts("1ippReadIO: Unable to allocate value"); + ipp_buffer_release(buffer); + return (IPP_ERROR); + } + + if ((*cb)(src, value->unknown.data, n) < n) + { + DEBUG_puts("1ippReadIO: Unable to read unsupported value."); + ipp_buffer_release(buffer); + return (IPP_ERROR); + } + } + else + value->unknown.data = NULL; + break; + } + + attr->num_values ++; - /* - * Get the name... + /* + * If blocking is disabled, stop here... */ - if ((*cb)(src, buffer, 2) < 2) - { - DEBUG_puts("1ippReadIO: unable to read name length."); - ipp_buffer_release(buffer); - return (IPP_ERROR); - } + if (!blocking) + break; + } + break; - n = (buffer[0] << 8) | buffer[1]; + case IPP_DATA : + break; - if (n >= IPP_BUF_SIZE) - { - _cupsSetError(IPP_ERROR, _("IPP name larger than 32767 bytes."), 1); - DEBUG_printf(("1ippReadIO: bad name length %d.", n)); - ipp_buffer_release(buffer); - return (IPP_ERROR); - } + default : + break; /* anti-compiler-warning-code */ + } - DEBUG_printf(("2ippReadIO: name length=%d", n)); + DEBUG_printf(("1ippReadIO: returning ipp->state=%d.", ipp->state)); + ipp_buffer_release(buffer); - if (n == 0 && tag != IPP_TAG_MEMBERNAME && - tag != IPP_TAG_END_COLLECTION) - { - /* - * More values for current attribute... - */ + return (ipp->state); +} - if (ipp->current == NULL) - { - _cupsSetError(IPP_ERROR, _("IPP attribute has no name."), 1); - DEBUG_puts("1ippReadIO: Attribute without name and no current."); - ipp_buffer_release(buffer); - return (IPP_ERROR); - } - attr = ipp->current; - value_tag = (ipp_tag_t)(attr->value_tag & IPP_TAG_MASK); +/* + * 'ippSetBoolean()' - Set a boolean value in an attribute. + * + * The @code ipp@ parameter refers to the IPP message containing the attribute that was + * previously created using the @link ippNew@ or @link ippNewRequest@ functions. + * + * The @code attr@ parameter may be modified as a result of setting the value. + * + * The @code element@ parameter specifies which value to set from 0 to + * @link ippGetCount(attr)@. + * + * @since CUPS 1.6@ + */ - /* - * Make sure we aren't adding a new value of a different - * type... - */ +int /* O - 1 on success, 0 on failure */ +ippSetBoolean(ipp_t *ipp, /* I - IPP message */ + ipp_attribute_t **attr, /* IO - IPP attribute */ + int element, /* I - Value number (0-based) */ + int boolvalue)/* I - Boolean value */ +{ + _ipp_value_t *value; /* Current value */ - if (value_tag == IPP_TAG_ZERO) - { - /* - * Setting the value of a collection member... - */ - attr->value_tag = tag; - } - else if (value_tag == IPP_TAG_TEXTLANG || - value_tag == IPP_TAG_NAMELANG || - (value_tag >= IPP_TAG_TEXT && - value_tag <= IPP_TAG_MIMETYPE)) - { - /* - * String values can sometimes come across in different - * forms; accept sets of differing values... - */ + /* + * Range check input... + */ - if (tag != IPP_TAG_TEXTLANG && tag != IPP_TAG_NAMELANG && - (tag < IPP_TAG_TEXT || tag > IPP_TAG_MIMETYPE) && - tag != IPP_TAG_NOVALUE) - { - _cupsSetError(IPP_ERROR, - _("IPP 1setOf attribute with incompatible value " - "tags."), 1); - DEBUG_printf(("1ippReadIO: 1setOf value tag %x(%s) != %x(%s)", - value_tag, ippTagString(value_tag), tag, - ippTagString(tag))); - ipp_buffer_release(buffer); - return (IPP_ERROR); - } - } - else if (value_tag == IPP_TAG_INTEGER || - value_tag == IPP_TAG_RANGE) - { - /* - * Integer and rangeOfInteger values can sometimes be mixed; accept - * sets of differing values... - */ + if (!ipp || !attr || !*attr || (*attr)->value_tag != IPP_TAG_BOOLEAN || + element < 0 || element > (*attr)->num_values) + return (0); - if (tag != IPP_TAG_INTEGER && tag != IPP_TAG_RANGE) - { - _cupsSetError(IPP_ERROR, - _("IPP 1setOf attribute with incompatible value " - "tags."), 1); - DEBUG_printf(("1ippReadIO: 1setOf value tag %x(%s) != %x(%s)", - value_tag, ippTagString(value_tag), tag, - ippTagString(tag))); - ipp_buffer_release(buffer); - return (IPP_ERROR); - } + /* + * Set the value and return... + */ - if (value_tag == IPP_TAG_INTEGER && tag == IPP_TAG_RANGE) - { - /* - * Convert integer values to rangeOfInteger values... - */ + if ((value = ipp_set_value(ipp, attr, element)) != NULL) + value->boolean = boolvalue; - int i; /* Looping var */ + return (value != NULL); +} - DEBUG_printf(("1ippReadIO: Converting %s attribute to " - "rangeOfInteger.", attr->name)); - attr->value_tag = IPP_TAG_RANGE; +/* + * 'ippSetCollection()' - Set a collection value in an attribute. + * + * The @code ipp@ parameter refers to the IPP message containing the attribute that was + * previously created using the @link ippNew@ or @link ippNewRequest@ functions. + * + * The @code attr@ parameter may be modified as a result of setting the value. + * + * The @code element@ parameter specifies which value to set from 0 to + * @link ippGetCount(attr)@. + * + * @since CUPS 1.6@ + */ - for (i = attr->num_values, value = attr->values; - i > 0; - i --, value ++) - { - n = value->integer; - value->range.lower = value->range.upper = n; - } - } - } - else if (value_tag != tag) - { - _cupsSetError(IPP_ERROR, - _("IPP 1setOf attribute with incompatible value " - "tags."), 1); - DEBUG_printf(("1ippReadIO: value tag %x(%s) != %x(%s)", - value_tag, ippTagString(value_tag), tag, - ippTagString(tag))); - ipp_buffer_release(buffer); - return (IPP_ERROR); - } +int /* O - 1 on success, 0 on failure */ +ippSetCollection( + ipp_t *ipp, /* I - IPP message */ + ipp_attribute_t **attr, /* IO - IPP attribute */ + int element, /* I - Value number (0-based) */ + ipp_t *colvalue) /* I - Collection value */ +{ + _ipp_value_t *value; /* Current value */ + + + /* + * Range check input... + */ + + if (!ipp || !attr || !*attr || (*attr)->value_tag != IPP_TAG_BEGIN_COLLECTION || + element < 0 || element > (*attr)->num_values || !colvalue) + return (0); + + /* + * Set the value and return... + */ + + if ((value = ipp_set_value(ipp, attr, element)) != NULL) + { + if (value->collection) + ippDelete(value->collection); + + value->collection = colvalue; + colvalue->use ++; + } + + return (value != NULL); +} + + +/* + * 'ippSetGroupTag()' - Set the group tag of an attribute. + * + * The @code ipp@ parameter refers to the IPP message containing the attribute that was + * previously created using the @link ippNew@ or @link ippNewRequest@ functions. + * + * The @code attr@ parameter may be modified as a result of setting the value. + * + * The @code group@ parameter specifies the IPP attribute group tag: none + * (@code IPP_TAG_ZERO@, for member attributes), document (@code IPP_TAG_DOCUMENT@), + * event notification (@code IPP_TAG_EVENT_NOTIFICATION@), operation + * (@code IPP_TAG_OPERATION@), printer (@code IPP_TAG_PRINTER@), subscription + * (@code IPP_TAG_SUBSCRIPTION@), or unsupported (@code IPP_TAG_UNSUPPORTED_GROUP@). + * + * @since CUPS 1.6@ + */ + +int /* O - 1 on success, 0 on failure */ +ippSetGroupTag( + ipp_t *ipp, /* I - IPP message */ + ipp_attribute_t **attr, /* IO - Attribute */ + ipp_tag_t group_tag) /* I - Group tag */ +{ + /* + * Range check input - group tag must be 0x01 to 0x0F, per RFC 2911... + */ + + if (!ipp || !attr || group_tag < IPP_TAG_ZERO || group_tag == IPP_TAG_END || + group_tag >= IPP_TAG_UNSUPPORTED_VALUE) + return (0); + + /* + * Set the group tag and return... + */ + + (*attr)->group_tag = group_tag; + + return (1); +} + + +/* + * 'ippSetInteger()' - Set an integer or enum value in an attribute. + * + * The @code ipp@ parameter refers to the IPP message containing the attribute that was + * previously created using the @link ippNew@ or @link ippNewRequest@ functions. + * + * The @code attr@ parameter may be modified as a result of setting the value. + * + * The @code element@ parameter specifies which value to set from 0 to + * @link ippGetCount(attr)@. + * + * @since CUPS 1.6@ + */ + +int /* O - 1 on success, 0 on failure */ +ippSetInteger(ipp_t *ipp, /* I - IPP message */ + ipp_attribute_t **attr, /* IO - IPP attribute */ + int element, /* I - Value number (0-based) */ + int intvalue) /* I - Integer/enum value */ +{ + _ipp_value_t *value; /* Current value */ + + + /* + * Range check input... + */ + + if (!ipp || !attr || !*attr || + ((*attr)->value_tag != IPP_TAG_INTEGER && (*attr)->value_tag != IPP_TAG_ENUM) || + element < 0 || element > (*attr)->num_values) + return (0); + + /* + * Set the value and return... + */ + + if ((value = ipp_set_value(ipp, attr, element)) != NULL) + value->integer = intvalue; + + return (value != NULL); +} + + +/* + * 'ippSetName()' - Set the name of an attribute. + * + * The @code ipp@ parameter refers to the IPP message containing the attribute that was + * previously created using the @link ippNew@ or @link ippNewRequest@ functions. + * + * The @code attr@ parameter may be modified as a result of setting the value. + * + * @since CUPS 1.6@ + */ + +int /* O - 1 on success, 0 on failure */ +ippSetName(ipp_t *ipp, /* I - IPP message */ + ipp_attribute_t **attr, /* IO - IPP attribute */ + const char *name) /* I - Attribute name */ +{ + char *temp; /* Temporary name value */ + + + /* + * Range check input... + */ + + if (!ipp || !attr || !*attr) + return (0); - /* - * Finally, reallocate the attribute array as needed... - */ + /* + * Set the value and return... + */ - if (attr->num_values == 1 || - (attr->num_values > 0 && - (attr->num_values & (IPP_MAX_VALUES - 1)) == 0)) - { - ipp_attribute_t *temp; /* Pointer to new buffer */ + if ((temp = _cupsStrAlloc(name)) != NULL) + { + if ((*attr)->name) + _cupsStrFree((*attr)->name); - DEBUG_printf(("2ippReadIO: reallocating for up to %d values...", - attr->num_values + IPP_MAX_VALUES)); + (*attr)->name = temp; + } - /* - * Reallocate memory... - */ + return (temp != NULL); +} - if ((temp = realloc(attr, sizeof(ipp_attribute_t) + - (attr->num_values + IPP_MAX_VALUES - 1) * - sizeof(ipp_value_t))) == NULL) - { - _cupsSetHTTPError(HTTP_ERROR); - DEBUG_puts("1ippReadIO: Unable to resize attribute"); - ipp_buffer_release(buffer); - return (IPP_ERROR); - } - if (temp != attr) - { - /* - * Reset pointers in the list... - */ +/* + * 'ippSetOperation()' - Set the operation ID in an IPP request message. + * + * The @code ipp@ parameter refers to an IPP message previously created using the + * @link ippNew@ or @link ippNewRequest@ functions. + * + * @since CUPS 1.6@ + */ - if (ipp->prev) - ipp->prev->next = temp; - else - ipp->attrs = temp; +int /* O - 1 on success, 0 on failure */ +ippSetOperation(ipp_t *ipp, /* I - IPP request message */ + ipp_op_t op) /* I - Operation ID */ +{ + /* + * Range check input... + */ - attr = ipp->current = ipp->last = temp; - } - } - } - else if (tag == IPP_TAG_MEMBERNAME) - { - /* - * Name must be length 0! - */ + if (!ipp) + return (0); - if (n) - { - _cupsSetError(IPP_ERROR, _("IPP member name is not empty."), 1); - DEBUG_puts("1ippReadIO: member name not empty."); - ipp_buffer_release(buffer); - return (IPP_ERROR); - } + /* + * Set the operation and return... + */ - if (ipp->current) - ipp->prev = ipp->current; + ipp->request.op.operation_id = op; - attr = ipp->current = _ippAddAttr(ipp, 1); + return (1); +} - DEBUG_printf(("2ippReadIO: membername, ipp->current=%p, " - "ipp->prev=%p", ipp->current, ipp->prev)); - attr->group_tag = ipp->curtag; - attr->value_tag = IPP_TAG_ZERO; - attr->num_values = 0; - } - else if (tag != IPP_TAG_END_COLLECTION) - { - /* - * New attribute; read the name and add it... - */ +/* + * 'ippSetRange()' - Set a rangeOfInteger value in an attribute. + * + * The @code ipp@ parameter refers to the IPP message containing the attribute that was + * previously created using the @link ippNew@ or @link ippNewRequest@ functions. + * + * The @code attr@ parameter may be modified as a result of setting the value. + * + * The @code element@ parameter specifies which value to set from 0 to + * @link ippGetCount(attr)@. + * + * @since CUPS 1.6@ + */ - if ((*cb)(src, buffer, n) < n) - { - DEBUG_puts("1ippReadIO: unable to read name."); - ipp_buffer_release(buffer); - return (IPP_ERROR); - } +int /* O - 1 on success, 0 on failure */ +ippSetRange(ipp_t *ipp, /* I - IPP message */ + ipp_attribute_t **attr, /* IO - IPP attribute */ + int element, /* I - Value number (0-based) */ + int lowervalue, /* I - Lower bound for range */ + int uppervalue) /* I - Upper bound for range */ +{ + _ipp_value_t *value; /* Current value */ - buffer[n] = '\0'; - if (ipp->current) - ipp->prev = ipp->current; + /* + * Range check input... + */ - if ((attr = ipp->current = _ippAddAttr(ipp, 1)) == NULL) - { - _cupsSetHTTPError(HTTP_ERROR); - DEBUG_puts("1ippReadIO: unable to allocate attribute."); - ipp_buffer_release(buffer); - return (IPP_ERROR); - } + if (!ipp || !attr || !*attr || (*attr)->value_tag != IPP_TAG_RANGE || + element < 0 || element > (*attr)->num_values || lowervalue > uppervalue) + return (0); - DEBUG_printf(("2ippReadIO: name=\"%s\", ipp->current=%p, " - "ipp->prev=%p", buffer, ipp->current, ipp->prev)); + /* + * Set the value and return... + */ - attr->group_tag = ipp->curtag; - attr->value_tag = tag; - attr->name = _cupsStrAlloc((char *)buffer); - attr->num_values = 0; - } - else - attr = NULL; + if ((value = ipp_set_value(ipp, attr, element)) != NULL) + { + value->range.lower = lowervalue; + value->range.upper = uppervalue; + } - if (tag != IPP_TAG_END_COLLECTION) - value = attr->values + attr->num_values; - else - value = NULL; + return (value != NULL); +} - if ((*cb)(src, buffer, 2) < 2) - { - DEBUG_puts("1ippReadIO: unable to read value length."); - ipp_buffer_release(buffer); - return (IPP_ERROR); - } - n = (buffer[0] << 8) | buffer[1]; - DEBUG_printf(("2ippReadIO: value length=%d", n)); +/* + * 'ippSetRequestId()' - Set the request ID in an IPP message. + * + * The @code ipp@ parameter refers to an IPP message previously created using the + * @link ippNew@ or @link ippNewRequest@ functions. + * + * The @code request_id@ parameter must be greater than 0. + * + * @since CUPS 1.6@ + */ - if (n >= IPP_BUF_SIZE) - { - _cupsSetError(IPP_ERROR, - _("IPP value larger than 32767 bytes."), 1); - DEBUG_printf(("1ippReadIO: bad value length %d.", n)); - ipp_buffer_release(buffer); - return (IPP_ERROR); - } +int /* O - 1 on success, 0 on failure */ +ippSetRequestId(ipp_t *ipp, /* I - IPP message */ + int request_id) /* I - Request ID */ +{ + /* + * Range check input; not checking request_id values since ipptool wants to send + * invalid values for conformance testing and a bad request_id does not affect the + * encoding of a message... + */ - switch (tag) - { - case IPP_TAG_INTEGER : - case IPP_TAG_ENUM : - if (n != 4) - { - if (tag == IPP_TAG_INTEGER) - _cupsSetError(IPP_ERROR, - _("IPP integer value not 4 bytes."), 1); - else - _cupsSetError(IPP_ERROR, - _("IPP enum value not 4 bytes."), 1); - DEBUG_printf(("1ippReadIO: bad value length %d.", n)); - ipp_buffer_release(buffer); - return (IPP_ERROR); - } + if (!ipp) + return (0); - if ((*cb)(src, buffer, 4) < 4) - { - DEBUG_puts("1ippReadIO: Unable to read integer value."); - ipp_buffer_release(buffer); - return (IPP_ERROR); - } + /* + * Set the request ID and return... + */ - n = (((((buffer[0] << 8) | buffer[1]) << 8) | buffer[2]) << 8) | - buffer[3]; + ipp->request.any.request_id = request_id; - if (attr->value_tag == IPP_TAG_RANGE) - value->range.lower = value->range.upper = n; - else - value->integer = n; - break; + return (1); +} - case IPP_TAG_BOOLEAN : - if (n != 1) - { - _cupsSetError(IPP_ERROR, _("IPP boolean value not 1 byte."), - 1); - DEBUG_printf(("1ippReadIO: bad value length %d.", n)); - ipp_buffer_release(buffer); - return (IPP_ERROR); - } - if ((*cb)(src, buffer, 1) < 1) - { - DEBUG_puts("1ippReadIO: Unable to read boolean value."); - ipp_buffer_release(buffer); - return (IPP_ERROR); - } +/* + * 'ippSetResolution()' - Set a resolution value in an attribute. + * + * The @code ipp@ parameter refers to the IPP message containing the attribute that was + * previously created using the @link ippNew@ or @link ippNewRequest@ functions. + * + * The @code attr@ parameter may be modified as a result of setting the value. + * + * The @code element@ parameter specifies which value to set from 0 to + * @link ippGetCount(attr)@. + * + * @since CUPS 1.6@ + */ - value->boolean = buffer[0]; - break; +int /* O - 1 on success, 0 on failure */ +ippSetResolution( + ipp_t *ipp, /* I - IPP message */ + ipp_attribute_t **attr, /* IO - IPP attribute */ + int element, /* I - Value number (0-based) */ + ipp_res_t unitsvalue, /* I - Resolution units */ + int xresvalue, /* I - Horizontal/cross feed resolution */ + int yresvalue) /* I - Vertical/feed resolution */ +{ + _ipp_value_t *value; /* Current value */ - case IPP_TAG_NOVALUE : - case IPP_TAG_NOTSETTABLE : - case IPP_TAG_DELETEATTR : - case IPP_TAG_ADMINDEFINE : - /* - * These value types are not supposed to have values, however - * some vendors (Brother) do not implement IPP correctly and so - * we need to map non-empty values to text... - */ - if (attr->value_tag == tag) - { - if (n == 0) - break; + /* + * Range check input... + */ - attr->value_tag = IPP_TAG_TEXT; - } + if (!ipp || !attr || !*attr || (*attr)->value_tag != IPP_TAG_RESOLUTION || + element < 0 || element > (*attr)->num_values || xresvalue <= 0 || yresvalue <= 0 || + unitsvalue < IPP_RES_PER_INCH || unitsvalue > IPP_RES_PER_CM) + return (0); - case IPP_TAG_TEXT : - case IPP_TAG_NAME : - case IPP_TAG_KEYWORD : - case IPP_TAG_URI : - case IPP_TAG_URISCHEME : - case IPP_TAG_CHARSET : - case IPP_TAG_LANGUAGE : - case IPP_TAG_MIMETYPE : - if ((*cb)(src, buffer, n) < n) - { - DEBUG_puts("1ippReadIO: unable to read string value."); - ipp_buffer_release(buffer); - return (IPP_ERROR); - } + /* + * Set the value and return... + */ - buffer[n] = '\0'; - value->string.text = _cupsStrAlloc((char *)buffer); - DEBUG_printf(("2ippReadIO: value=\"%s\"", value->string.text)); - break; + if ((value = ipp_set_value(ipp, attr, element)) != NULL) + { + value->resolution.units = unitsvalue; + value->resolution.xres = xresvalue; + value->resolution.yres = yresvalue; + } - case IPP_TAG_DATE : - if (n != 11) - { - _cupsSetError(IPP_ERROR, _("IPP date value not 11 bytes."), - 1); - DEBUG_printf(("1ippReadIO: bad value length %d.", n)); - ipp_buffer_release(buffer); - return (IPP_ERROR); - } + return (value != NULL); +} - if ((*cb)(src, value->date, 11) < 11) - { - DEBUG_puts("1ippReadIO: Unable to read date value."); - ipp_buffer_release(buffer); - return (IPP_ERROR); - } - break; - case IPP_TAG_RESOLUTION : - if (n != 9) - { - _cupsSetError(IPP_ERROR, - _("IPP resolution value not 9 bytes."), 1); - DEBUG_printf(("1ippReadIO: bad value length %d.", n)); - ipp_buffer_release(buffer); - return (IPP_ERROR); - } +/* + * 'ippSetStatusCode()' - Set the status code in an IPP response or event message. + * + * The @code ipp@ parameter refers to an IPP message previously created using the + * @link ippNew@ or @link ippNewRequest@ functions. + * + * @since CUPS 1.6@ + */ - if ((*cb)(src, buffer, 9) < 9) - { - DEBUG_puts("1ippReadIO: Unable to read resolution value."); - ipp_buffer_release(buffer); - return (IPP_ERROR); - } +int /* O - 1 on success, 0 on failure */ +ippSetStatusCode(ipp_t *ipp, /* I - IPP response or event message */ + ipp_status_t status) /* I - Status code */ +{ + /* + * Range check input... + */ + + if (!ipp) + return (0); - value->resolution.xres = - (((((buffer[0] << 8) | buffer[1]) << 8) | buffer[2]) << 8) | - buffer[3]; - value->resolution.yres = - (((((buffer[4] << 8) | buffer[5]) << 8) | buffer[6]) << 8) | - buffer[7]; - value->resolution.units = - (ipp_res_t)buffer[8]; - break; + /* + * Set the status code and return... + */ - case IPP_TAG_RANGE : - if (n != 8) - { - _cupsSetError(IPP_ERROR, - _("IPP rangeOfInteger value not 8 bytes."), 1); - DEBUG_printf(("1ippReadIO: bad value length %d.", n)); - ipp_buffer_release(buffer); - return (IPP_ERROR); - } + ipp->request.status.status_code = status; - if ((*cb)(src, buffer, 8) < 8) - { - DEBUG_puts("1ippReadIO: Unable to read range value."); - ipp_buffer_release(buffer); - return (IPP_ERROR); - } + return (1); - value->range.lower = - (((((buffer[0] << 8) | buffer[1]) << 8) | buffer[2]) << 8) | - buffer[3]; - value->range.upper = - (((((buffer[4] << 8) | buffer[5]) << 8) | buffer[6]) << 8) | - buffer[7]; - break; +} - case IPP_TAG_TEXTLANG : - case IPP_TAG_NAMELANG : - if (n < 4) - { - if (tag == IPP_TAG_TEXTLANG) - _cupsSetError(IPP_ERROR, - _("IPP textWithLanguage value less than " - "minimum 4 bytes."), 1); - else - _cupsSetError(IPP_ERROR, - _("IPP nameWithLanguage value less than " - "minimum 4 bytes."), 1); - DEBUG_printf(("1ippReadIO: bad value length %d.", n)); - ipp_buffer_release(buffer); - return (IPP_ERROR); - } - if ((*cb)(src, buffer, n) < n) - { - DEBUG_puts("1ippReadIO: Unable to read string w/language " - "value."); - ipp_buffer_release(buffer); - return (IPP_ERROR); - } +/* + * 'ippSetString()' - Set a string value in an attribute. + * + * The @code ipp@ parameter refers to the IPP message containing the attribute that was + * previously created using the @link ippNew@ or @link ippNewRequest@ functions. + * + * The @code attr@ parameter may be modified as a result of setting the value. + * + * The @code element@ parameter specifies which value to set from 0 to + * @link ippGetCount(attr)@. + * + * @since CUPS 1.6@ + */ - bufptr = buffer; +int /* O - 1 on success, 0 on failure */ +ippSetString(ipp_t *ipp, /* I - IPP message */ + ipp_attribute_t **attr, /* IO - IPP attribute */ + int element, /* I - Value number (0-based) */ + const char *strvalue) /* I - String value */ +{ + char *temp; /* Temporary string */ + _ipp_value_t *value; /* Current value */ - /* - * text-with-language and name-with-language are composite - * values: - * - * language-length - * language - * text-length - * text - * - * The "charset" field name is an unfortunate typo from - * CUPS 1.0... - */ - n = (bufptr[0] << 8) | bufptr[1]; + /* + * Range check input... + */ - if ((bufptr + 2 + n) >= (buffer + IPP_BUF_SIZE) || - n >= sizeof(string)) - { - _cupsSetError(IPP_ERROR, - _("IPP language length overflows value."), 1); - DEBUG_printf(("1ippReadIO: bad value length %d.", n)); - ipp_buffer_release(buffer); - return (IPP_ERROR); - } + if (!ipp || !attr || !*attr || (*attr)->value_tag != IPP_TAG_INTEGER || + element < 0 || element > (*attr)->num_values || !strvalue) + return (0); - memcpy(string, bufptr + 2, n); - string[n] = '\0'; + /* + * Set the value and return... + */ - value->string.charset = _cupsStrAlloc((char *)string); + if ((value = ipp_set_value(ipp, attr, element)) != NULL) + { + if (element > 0) + value->string.language = (*attr)->values[0].string.language; - bufptr += 2 + n; - n = (bufptr[0] << 8) | bufptr[1]; + if ((int)((*attr)->value_tag) & IPP_TAG_COPY) + value->string.text = (char *)strvalue; + else if ((temp = _cupsStrAlloc(strvalue)) != NULL) + { + if (value->string.text) + _cupsStrFree(value->string.text); - if ((bufptr + 2 + n) >= (buffer + IPP_BUF_SIZE)) - { - _cupsSetError(IPP_ERROR, - _("IPP string length overflows value."), 1); - DEBUG_printf(("1ippReadIO: bad value length %d.", n)); - ipp_buffer_release(buffer); - return (IPP_ERROR); - } + value->string.text = temp; + } + else + return (0); + } - bufptr[2 + n] = '\0'; - value->string.text = _cupsStrAlloc((char *)bufptr + 2); - break; + return (value != NULL); +} - case IPP_TAG_BEGIN_COLLECTION : - /* - * Oh, boy, here comes a collection value, so read it... - */ - value->collection = ippNew(); +/* + * 'ippSetValueTag()' - Set the value tag of an attribute. + * + * The @code ipp@ parameter refers to the IPP message containing the attribute that was + * previously created using the @link ippNew@ or @link ippNewRequest@ functions. + * + * The @code attr@ parameter may be modified as a result of setting the value. + * + * Integer (@code IPP_TAG_INTEGER@) values can be promoted to rangeOfInteger + * (@code IPP_TAG_RANGE@) values, the various string tags can be promoted to name + * (@code IPP_TAG_NAME@) or nameWithLanguage (@code IPP_TAG_NAMELANG@) values, text + * (@code IPP_TAG_TEXT@) values can be promoted to textWithLanguage + * (@code IPP_TAG_TEXTLANG@) values, and all values can be demoted to the various + * out-of-band value tags such as no-value (@code IPP_TAG_NOVALUE@). All other changes + * will be rejected. + * + * Promoting a string attribute to nameWithLanguage or textWithLanguage adds the language + * code in the "attributes-natural-language" attribute or, if not present, the language + * code for the current locale. + * + * @since CUPS 1.6@ + */ - if (n > 0) - { - _cupsSetError(IPP_ERROR, - _("IPP begCollection value not 0 bytes."), 1); - DEBUG_puts("1ippReadIO: begCollection tag with value length " - "> 0."); - ipp_buffer_release(buffer); - return (IPP_ERROR); - } +int /* O - 1 on success, 0 on failure */ +ippSetValueTag( + ipp_t *ipp, /* I - IPP message */ + ipp_attribute_t **attr, /* IO - IPP attribute */ + ipp_tag_t value_tag) /* I - Value tag */ +{ + int i; /* Looping var */ + _ipp_value_t *value; /* Current value */ + int integer; /* Current integer value */ + cups_lang_t *language; /* Current language */ + char code[32]; /* Language code */ + ipp_tag_t temp_tag; /* Temporary value tag */ - if (ippReadIO(src, cb, 1, ipp, value->collection) == IPP_ERROR) - { - DEBUG_puts("1ippReadIO: Unable to read collection value."); - ipp_buffer_release(buffer); - return (IPP_ERROR); - } - break; - case IPP_TAG_END_COLLECTION : - ipp_buffer_release(buffer); + /* + * Range check input... + */ - if (n > 0) - { - _cupsSetError(IPP_ERROR, - _("IPP endCollection value not 0 bytes."), 1); - DEBUG_puts("1ippReadIO: endCollection tag with value length " - "> 0."); - return (IPP_ERROR); - } + if (!ipp || !attr) + return (0); - DEBUG_puts("1ippReadIO: endCollection tag..."); - return (ipp->state = IPP_DATA); + /* + * If there is no change, return immediately... + */ - case IPP_TAG_MEMBERNAME : - /* - * The value the name of the member in the collection, which - * we need to carry over... - */ + if (value_tag == (*attr)->value_tag) + return (1); - if ((*cb)(src, buffer, n) < n) - { - DEBUG_puts("1ippReadIO: Unable to read member name value."); - ipp_buffer_release(buffer); - return (IPP_ERROR); - } + /* + * Otherwise implement changes as needed... + */ - buffer[n] = '\0'; - attr->name = _cupsStrAlloc((char *)buffer); + temp_tag = (ipp_tag_t)((int)((*attr)->value_tag) & IPP_TAG_MASK); - /* - * Since collection members are encoded differently than - * regular attributes, make sure we don't start with an - * empty value... - */ + switch (value_tag) + { + case IPP_TAG_UNSUPPORTED_VALUE : + case IPP_TAG_DEFAULT : + case IPP_TAG_UNKNOWN : + case IPP_TAG_NOVALUE : + case IPP_TAG_NOTSETTABLE : + case IPP_TAG_DELETEATTR : + case IPP_TAG_ADMINDEFINE : + /* + * Free any existing values... + */ - attr->num_values --; + if ((*attr)->num_values > 0) + ipp_free_values(*attr, 0, (*attr)->num_values); - DEBUG_printf(("2ippReadIO: member name=\"%s\"", attr->name)); - break; + /* + * Set out-of-band value... + */ - default : /* Other unsupported values */ - value->unknown.length = n; - if (n > 0) - { - if ((value->unknown.data = malloc(n)) == NULL) - { - _cupsSetHTTPError(HTTP_ERROR); - DEBUG_puts("1ippReadIO: Unable to allocate value"); - ipp_buffer_release(buffer); - return (IPP_ERROR); - } + (*attr)->value_tag = value_tag; + break; - if ((*cb)(src, value->unknown.data, n) < n) - { - DEBUG_puts("1ippReadIO: Unable to read unsupported value."); - ipp_buffer_release(buffer); - return (IPP_ERROR); - } - } - else - value->unknown.data = NULL; - break; - } + case IPP_TAG_RANGE : + if (temp_tag != IPP_TAG_INTEGER) + return (0); + + for (i = (*attr)->num_values, value = (*attr)->values; + i > 0; + i --, value ++) + { + integer = value->integer; + value->range.lower = value->range.upper = integer; + } - attr->num_values ++; + (*attr)->value_tag = IPP_TAG_RANGE; + break; - /* - * If blocking is disabled, stop here... - */ + case IPP_TAG_NAME : + if (temp_tag != IPP_TAG_KEYWORD && temp_tag != IPP_TAG_URI && + temp_tag != IPP_TAG_URISCHEME && temp_tag != IPP_TAG_LANGUAGE && + temp_tag != IPP_TAG_MIMETYPE) + return (0); - if (!blocking) - break; - } + (*attr)->value_tag = (ipp_tag_t)(IPP_TAG_NAME | ((*attr)->value_tag & IPP_TAG_COPY)); break; - case IPP_DATA : + case IPP_TAG_NAMELANG : + case IPP_TAG_TEXTLANG : + if (value_tag == IPP_TAG_NAMELANG && + (temp_tag != IPP_TAG_NAME && temp_tag != IPP_TAG_KEYWORD && + temp_tag != IPP_TAG_URI && temp_tag != IPP_TAG_URISCHEME && + temp_tag != IPP_TAG_LANGUAGE && temp_tag != IPP_TAG_MIMETYPE)) + return (0); + + if (value_tag == IPP_TAG_TEXTLANG && temp_tag != IPP_TAG_TEXT) + return (0); + + if (ipp->attrs && ipp->attrs->next && ipp->attrs->next->name && + !strcmp(ipp->attrs->next->name, "attributes-natural-language")) + { + /* + * Use the language code from the IPP message... + */ + + (*attr)->values[0].string.language = + _cupsStrAlloc(ipp->attrs->next->values[0].string.text); + } + else + { + /* + * Otherwise, use the language code corresponding to the locale... + */ + + language = cupsLangDefault(); + (*attr)->values[0].string.language = _cupsStrAlloc(ipp_lang_code(language->language, + code, + sizeof(code))); + } + + for (i = (*attr)->num_values - 1, value = (*attr)->values + 1; + i > 0; + i --, value ++) + value->string.language = (*attr)->values[0].string.language; + + if ((int)(*attr)->value_tag & IPP_TAG_COPY) + { + /* + * Make copies of all values... + */ + + for (i = (*attr)->num_values, value = (*attr)->values; + i > 0; + i --, value ++) + value->string.text = _cupsStrAlloc(value->string.text); + } + + (*attr)->value_tag = IPP_TAG_NAMELANG; break; + case IPP_TAG_KEYWORD : + if (temp_tag == IPP_TAG_NAME || temp_tag == IPP_TAG_NAMELANG) + break; /* Silently "allow" name -> keyword */ + default : - break; /* anti-compiler-warning-code */ + return (0); } - DEBUG_printf(("1ippReadIO: returning ipp->state=%d.", ipp->state)); - ipp_buffer_release(buffer); + return (1); +} + + +/* + * 'ippSetVersion()' - Set the version number in an IPP message. + * + * The @code ipp@ parameter refers to an IPP message previously created using the + * @link ippNew@ or @link ippNewRequest@ functions. + * + * The valid version numbers are currently 1.0, 1.1, 2.0, 2.1, and 2.2. + * + * @since CUPS 1.6@ + */ + +int /* O - 1 on success, 0 on failure */ +ippSetVersion(ipp_t *ipp, /* I - IPP message */ + int major, /* I - Major version number (major.minor) */ + int minor) /* I - Minor version number (major.minor) */ +{ + /* + * Range check input... + */ + + if (!ipp || major < 0 || minor < 0) + return (0); + + /* + * Set the version number... + */ + + ipp->request.any.version[0] = major; + ipp->request.any.version[1] = minor; - return (ipp->state); + return (1); } @@ -1931,7 +3793,7 @@ ippWriteIO(void *dst, /* I - Destination */ unsigned char *buffer, /* Data buffer */ *bufptr; /* Pointer into buffer */ ipp_attribute_t *attr; /* Current attribute */ - ipp_value_t *value; /* Current value */ + _ipp_value_t *value; /* Current value */ DEBUG_printf(("ippWriteIO(dst=%p, cb=%p, blocking=%d, parent=%p, ipp=%p)", @@ -2044,9 +3906,7 @@ ippWriteIO(void *dst, /* I - Destination */ ippTagString(attr->value_tag))); /* - * Write the attribute tag and name. The current implementation - * does not support the extension value tags above 0x7f, so all - * value tags are 1 byte. + * Write the attribute tag and name. * * The attribute name length does not include the trailing nul * character in the source string. @@ -2061,7 +3921,7 @@ ippWriteIO(void *dst, /* I - Destination */ * overflow the buffer... */ - if ((n = (int)strlen(attr->name)) > (IPP_BUF_SIZE - 4)) + if ((n = (int)strlen(attr->name)) > (IPP_BUF_SIZE - 8)) { DEBUG_printf(("1ippWriteIO: Attribute name too long (%d)", n)); ipp_buffer_release(buffer); @@ -2077,7 +3937,17 @@ ippWriteIO(void *dst, /* I - Destination */ DEBUG_printf(("2ippWriteIO: writing name=%d,\"%s\"", n, attr->name)); - *bufptr++ = attr->value_tag; + if (attr->value_tag > 0xff) + { + *bufptr++ = IPP_TAG_EXTENSION; + *bufptr++ = attr->value_tag >> 24; + *bufptr++ = attr->value_tag >> 16; + *bufptr++ = attr->value_tag >> 8; + *bufptr++ = attr->value_tag; + } + else + *bufptr++ = attr->value_tag; + *bufptr++ = n >> 8; *bufptr++ = n; memcpy(bufptr, attr->name, n); @@ -2090,7 +3960,7 @@ ippWriteIO(void *dst, /* I - Destination */ * overflow the buffer... */ - if ((n = (int)strlen(attr->name)) > (IPP_BUF_SIZE - 7)) + if ((n = (int)strlen(attr->name)) > (IPP_BUF_SIZE - 12)) { DEBUG_printf(("1ippWriteIO: Attribute name too long (%d)", n)); ipp_buffer_release(buffer); @@ -2118,7 +3988,17 @@ ippWriteIO(void *dst, /* I - Destination */ memcpy(bufptr, attr->name, n); bufptr += n; - *bufptr++ = attr->value_tag; + if (attr->value_tag > 0xff) + { + *bufptr++ = IPP_TAG_EXTENSION; + *bufptr++ = attr->value_tag >> 24; + *bufptr++ = attr->value_tag >> 16; + *bufptr++ = attr->value_tag >> 8; + *bufptr++ = attr->value_tag; + } + else + *bufptr++ = attr->value_tag; + *bufptr++ = 0; *bufptr++ = 0; } @@ -2129,6 +4009,17 @@ ippWriteIO(void *dst, /* I - Destination */ switch (attr->value_tag & ~IPP_TAG_COPY) { + case IPP_TAG_UNSUPPORTED_VALUE : + case IPP_TAG_DEFAULT : + case IPP_TAG_UNKNOWN : + case IPP_TAG_NOVALUE : + case IPP_TAG_NOTSETTABLE : + case IPP_TAG_DELETEATTR : + case IPP_TAG_ADMINDEFINE : + *bufptr++ = 0; + *bufptr++ = 0; + break; + case IPP_TAG_INTEGER : case IPP_TAG_ENUM : for (i = 0, value = attr->values; @@ -2501,8 +4392,8 @@ ippWriteIO(void *dst, /* I - Destination */ n = 4; - if (value->string.charset != NULL) - n += (int)strlen(value->string.charset); + if (value->string.language != NULL) + n += (int)strlen(value->string.language); if (value->string.text != NULL) n += (int)strlen(value->string.text); @@ -2532,19 +4423,19 @@ ippWriteIO(void *dst, /* I - Destination */ *bufptr++ = n >> 8; *bufptr++ = n; - /* Length of charset */ - if (value->string.charset != NULL) - n = (int)strlen(value->string.charset); + /* Length of language */ + if (value->string.language != NULL) + n = (int)strlen(value->string.language); else n = 0; *bufptr++ = n >> 8; *bufptr++ = n; - /* Charset */ + /* Language */ if (n > 0) { - memcpy(bufptr, value->string.charset, n); + memcpy(bufptr, value->string.language, n); bufptr += n; } @@ -2782,122 +4673,71 @@ ippWriteIO(void *dst, /* I - Destination */ /* - * '_ippAddAttr()' - Add a new attribute to the request. + * 'ipp_add_attr()' - Add a new attribute to the message. */ -ipp_attribute_t * /* O - New attribute */ -_ippAddAttr(ipp_t *ipp, /* I - IPP message */ - int num_values) /* I - Number of values */ +static ipp_attribute_t * /* O - New attribute */ +ipp_add_attr(ipp_t *ipp, /* I - IPP message */ + const char *name, /* I - Attribute name or NULL */ + ipp_tag_t group_tag, /* I - Group tag or IPP_TAG_ZERO */ + ipp_tag_t value_tag, /* I - Value tag or IPP_TAG_ZERO */ + int num_values) /* I - Number of values */ { + int alloc_values; /* Number of values to allocate */ ipp_attribute_t *attr; /* New attribute */ - DEBUG_printf(("4_ippAddAttr(ipp=%p, num_values=%d)", ipp, num_values)); + DEBUG_printf(("4ipp_add_attr(ipp=%p, name=\"%s\", group_tag=0x%x, value_tag=0x%x, " + "num_values=%d)", ipp, name, group_tag, value_tag, num_values)); + + /* + * Range check input... + */ if (!ipp || num_values < 0) return (NULL); - attr = calloc(sizeof(ipp_attribute_t) + - (num_values - 1) * sizeof(ipp_value_t), 1); - - if (attr != NULL) - { - attr->num_values = num_values; - - if (ipp->last == NULL) - ipp->attrs = attr; - else - ipp->last->next = attr; - - ipp->last = attr; - } - - DEBUG_printf(("5_ippAddAttr: Returning %p", attr)); - - return (attr); -} - - -/* - * '_ippFreeAttr()' - Free an attribute. - */ - -void -_ippFreeAttr(ipp_attribute_t *attr) /* I - Attribute to free */ -{ - int i; /* Looping var */ - ipp_value_t *value; /* Current value */ + /* + * Allocate memory, rounding the allocation up as needed... + */ + if (num_values <= 1) + alloc_values = num_values; + else + alloc_values = (num_values + IPP_MAX_VALUES - 1) & ~(IPP_MAX_VALUES - 1); - DEBUG_printf(("4_ippFreeAttr(attr=%p)", attr)); + attr = calloc(sizeof(ipp_attribute_t) + + (alloc_values - 1) * sizeof(_ipp_value_t), 1); - switch (attr->value_tag) + if (attr) { - case IPP_TAG_TEXT : - case IPP_TAG_NAME : - case IPP_TAG_RESERVED_STRING : - case IPP_TAG_KEYWORD : - case IPP_TAG_URI : - case IPP_TAG_URISCHEME : - case IPP_TAG_CHARSET : - case IPP_TAG_LANGUAGE : - case IPP_TAG_MIMETYPE : - for (i = 0, value = attr->values; - i < attr->num_values; - i ++, value ++) - _cupsStrFree(value->string.text); - break; + /* + * Initialize attribute... + */ - case IPP_TAG_TEXTLANG : - case IPP_TAG_NAMELANG : - for (i = 0, value = attr->values; - i < attr->num_values; - i ++, value ++) - { - if (value->string.charset && i == 0) - _cupsStrFree(value->string.charset); - _cupsStrFree(value->string.text); - } - break; + if (name) + attr->name = _cupsStrAlloc(name); - case IPP_TAG_INTEGER : - case IPP_TAG_ENUM : - case IPP_TAG_BOOLEAN : - case IPP_TAG_DATE : - case IPP_TAG_RESOLUTION : - case IPP_TAG_RANGE : - break; + attr->group_tag = group_tag; + attr->value_tag = value_tag; + attr->num_values = num_values; - case IPP_TAG_BEGIN_COLLECTION : - for (i = 0, value = attr->values; - i < attr->num_values; - i ++, value ++) - ippDelete(value->collection); - break; + /* + * Add it to the end of the linked list... + */ - case IPP_TAG_STRING : - for (i = 0, value = attr->values; - i < attr->num_values; - i ++, value ++) - free(value->unknown.data); - break; + if (ipp->last) + ipp->last->next = attr; + else + ipp->attrs = attr; - default : - if (!((int)attr->value_tag & IPP_TAG_COPY)) - { - for (i = 0, value = attr->values; - i < attr->num_values; - i ++, value ++) - if (value->unknown.data) - free(value->unknown.data); - } - break; + ipp->prev = ipp->last; + ipp->last = ipp->current = attr; } - if (attr->name) - _cupsStrFree(attr->name); + DEBUG_printf(("5ipp_add_attr: Returning %p", attr)); - free(attr); + return (attr); } @@ -2942,6 +4782,157 @@ ipp_buffer_release(unsigned char *b) /* I - Buffer to release */ } +/* + * 'ipp_free_values()' - Free attribute values. + */ + +static void +ipp_free_values(ipp_attribute_t *attr, /* I - Attribute to free values from */ + int element,/* I - First value to free */ + int count) /* I - Number of values to free */ +{ + int i; /* Looping var */ + _ipp_value_t *value; /* Current value */ + + + DEBUG_printf(("4ipp_free_values(attr=%p, element=%d, count=%d)", attr, element, count)); + + if (!(attr->value_tag & IPP_TAG_COPY)) + { + /* + * Free values as needed... + */ + + switch (attr->value_tag) + { + case IPP_TAG_TEXTLANG : + case IPP_TAG_NAMELANG : + if (element == 0 && count == attr->num_values && attr->values[0].string.language) + _cupsStrFree(attr->values[0].string.language); + + case IPP_TAG_TEXT : + case IPP_TAG_NAME : + case IPP_TAG_RESERVED_STRING : + case IPP_TAG_KEYWORD : + case IPP_TAG_URI : + case IPP_TAG_URISCHEME : + case IPP_TAG_CHARSET : + case IPP_TAG_LANGUAGE : + case IPP_TAG_MIMETYPE : + for (i = count, value = attr->values + element; + i > 0; + i --, value ++) + _cupsStrFree(value->string.text); + break; + + case IPP_TAG_DEFAULT : + case IPP_TAG_UNKNOWN : + case IPP_TAG_NOVALUE : + case IPP_TAG_NOTSETTABLE : + case IPP_TAG_DELETEATTR : + case IPP_TAG_ADMINDEFINE : + case IPP_TAG_INTEGER : + case IPP_TAG_ENUM : + case IPP_TAG_BOOLEAN : + case IPP_TAG_DATE : + case IPP_TAG_RESOLUTION : + case IPP_TAG_RANGE : + break; + + case IPP_TAG_BEGIN_COLLECTION : + for (i = count, value = attr->values + element; + i > 0; + i --, value ++) + ippDelete(value->collection); + break; + + case IPP_TAG_STRING : + default : + for (i = count, value = attr->values + element; + i > 0; + i --, value ++) + if (value->unknown.data) + free(value->unknown.data); + break; + } + } + + /* + * If we are not freeing values from the end, move the remaining values up... + */ + + if ((element + count) < attr->num_values) + memmove(attr->values + element, attr->values + element + count, + (attr->num_values - count - element) * sizeof(_ipp_value_t)); + + attr->num_values -= count; +} + + +/* + * 'ipp_get_code()' - Convert a C locale/charset name into an IPP language/charset code. + * + * This typically converts strings of the form "ll_CC", "ll-REGION", and "CHARSET_NUMBER" + * to "ll-cc", "ll-region", and "charset-number", respectively. + */ + +static char * /* O - Language code string */ +ipp_get_code(const char *value, /* I - Locale/charset string */ + char *buffer, /* I - String buffer */ + size_t bufsize) /* I - Size of string buffer */ +{ + char *bufptr, /* Pointer into buffer */ + *bufend; /* End of buffer */ + + + /* + * Convert values to lowercase and change _ to - as needed... + */ + + for (bufptr = buffer, bufend = buffer + bufsize - 1; + *value && bufptr < bufend; + value ++) + if (*value == '_') + *bufptr++ = '-'; + else + *bufptr++ = _cups_tolower(*value); + + *bufptr = '\0'; + + /* + * Return the converted string... + */ + + return (buffer); +} + + +/* + * 'ipp_lang_code()' - Convert a C locale name into an IPP language code. + * + * This typically converts strings of the form "ll_CC" and "ll-REGION" to "ll-cc" and + * "ll-region", respectively. It also converts the "C" (POSIX) locale to "en". + */ + +static char * /* O - Language code string */ +ipp_lang_code(const char *locale, /* I - Locale string */ + char *buffer, /* I - String buffer */ + size_t bufsize) /* I - Size of string buffer */ +{ + /* + * Map POSIX ("C") locale to generic English, otherwise convert the locale string as-is. + */ + + if (!_cups_strcasecmp(locale, "c")) + { + strlcpy(buffer, "en", bufsize); + return (buffer); + } + else + return (ipp_get_code(locale, buffer, bufsize)); +} + + /* * 'ipp_length()' - Compute the length of an IPP message or collection value. */ @@ -2951,14 +4942,19 @@ ipp_length(ipp_t *ipp, /* I - IPP message or collection */ int collection) /* I - 1 if a collection, 0 otherwise */ { int i; /* Looping var */ - int bytes; /* Number of bytes */ + size_t bytes; /* Number of bytes */ ipp_attribute_t *attr; /* Current attribute */ ipp_tag_t group; /* Current group */ - ipp_value_t *value; /* Current value */ + _ipp_value_t *value; /* Current value */ + + DEBUG_printf(("3ipp_length(ipp=%p, collection=%d)", ipp, collection)); - if (ipp == NULL) + if (!ipp) + { + DEBUG_puts("4ipp_length: Returning 0 bytes"); return (0); + } /* * Start with 8 bytes for the IPP message header... @@ -2986,12 +4982,15 @@ ipp_length(ipp_t *ipp, /* I - IPP message or collection */ if (!attr->name) continue; - DEBUG_printf(("9ipp_length: attr->name=\"%s\", attr->num_values=%d, " - "bytes=%d", attr->name, attr->num_values, bytes)); + DEBUG_printf(("5ipp_length: attr->name=\"%s\", attr->num_values=%d, " + "bytes=" CUPS_LLFMT, attr->name, attr->num_values, CUPS_LLCAST bytes)); - bytes += (int)strlen(attr->name); /* Name */ - bytes += attr->num_values; /* Value tag for each value */ + if (attr->value_tag < IPP_TAG_EXTENSION) + bytes += attr->num_values; /* Value tag for each value */ + else + bytes += 5 * attr->num_values; /* Value tag for each value */ bytes += 2 * attr->num_values; /* Name lengths */ + bytes += (int)strlen(attr->name); /* Name */ bytes += 2 * attr->num_values; /* Value lengths */ if (collection) @@ -2999,6 +4998,15 @@ ipp_length(ipp_t *ipp, /* I - IPP message or collection */ switch (attr->value_tag & ~IPP_TAG_COPY) { + case IPP_TAG_UNSUPPORTED_VALUE : + case IPP_TAG_DEFAULT : + case IPP_TAG_UNKNOWN : + case IPP_TAG_NOVALUE : + case IPP_TAG_NOTSETTABLE : + case IPP_TAG_DELETEATTR : + case IPP_TAG_ADMINDEFINE : + break; + case IPP_TAG_INTEGER : case IPP_TAG_ENUM : bytes += 4 * attr->num_values; @@ -3019,8 +5027,8 @@ ipp_length(ipp_t *ipp, /* I - IPP message or collection */ for (i = 0, value = attr->values; i < attr->num_values; i ++, value ++) - if (value->string.text != NULL) - bytes += (int)strlen(value->string.text); + if (value->string.text) + bytes += strlen(value->string.text); break; case IPP_TAG_DATE : @@ -3043,11 +5051,11 @@ ipp_length(ipp_t *ipp, /* I - IPP message or collection */ i < attr->num_values; i ++, value ++) { - if (value->string.charset != NULL) - bytes += (int)strlen(value->string.charset); + if (value->string.language) + bytes += strlen(value->string.language); - if (value->string.text != NULL) - bytes += (int)strlen(value->string.text); + if (value->string.text) + bytes += strlen(value->string.text); } break; @@ -3055,7 +5063,7 @@ ipp_length(ipp_t *ipp, /* I - IPP message or collection */ for (i = 0, value = attr->values; i < attr->num_values; i ++, value ++) - bytes += (int)ipp_length(value->collection, 1); + bytes += ipp_length(value->collection, 1); break; default : @@ -3077,7 +5085,7 @@ ipp_length(ipp_t *ipp, /* I - IPP message or collection */ else bytes ++; - DEBUG_printf(("8ipp_length: Returning %d bytes", bytes)); + DEBUG_printf(("4ipp_length: Returning " CUPS_LLFMT " bytes", CUPS_LLCAST bytes)); return (bytes); } @@ -3231,6 +5239,126 @@ ipp_read_file(int *fd, /* I - File descriptor */ } +/* + * 'ipp_set_value()' - Get the value element from an attribute, expanding it as needed. + */ + +static _ipp_value_t * /* O - IPP value element or NULL on error */ +ipp_set_value(ipp_t *ipp, /* I - IPP message */ + ipp_attribute_t **attr, /* IO - IPP attribute */ + int element) /* I - Value number (0-based) */ +{ + ipp_attribute_t *temp, /* New attribute pointer */ + *current, /* Current attribute in list */ + *prev; /* Previous attribute in list */ + int alloc_values; /* Allocated values */ + + + /* + * If we are setting an existing value element, return it... + */ + + temp = *attr; + + if (temp->num_values <= 1) + alloc_values = temp->num_values; + else + alloc_values = (temp->num_values + IPP_MAX_VALUES - 1) & ~(IPP_MAX_VALUES - 1); + + if (element < alloc_values) + return (temp->values + element); + + /* + * Otherwise re-allocate the attribute - we allocate in groups of IPP_MAX_VALUE values + * when num_values > 1. + */ + + if (alloc_values < IPP_MAX_VALUES) + alloc_values = IPP_MAX_VALUES; + else + alloc_values += IPP_MAX_VALUES; + + DEBUG_printf(("4ipp_set_value: Reallocating for up to %d values.", alloc_values)); + + /* + * Reallocate memory... + */ + + if ((temp = realloc(temp, sizeof(ipp_attribute_t) + + (temp->num_values + IPP_MAX_VALUES - 1) * + sizeof(_ipp_value_t))) == NULL) + { + _cupsSetHTTPError(HTTP_ERROR); + DEBUG_puts("4ipp_set_value: Unable to resize attribute."); + return (NULL); + } + + /* + * Zero the new memory... + */ + + memset(temp->values + temp->num_values, 0, + (alloc_values - temp->num_values) * sizeof(_ipp_value_t)); + + if (temp != *attr) + { + /* + * Reset pointers in the list... + */ + + if (ipp->current == *attr && ipp->prev) + { + /* + * Use current "previous" pointer... + */ + + prev = ipp->prev; + } + else + { + /* + * Find this attribute in the linked list... + */ + + for (prev = NULL, current = ipp->attrs; + current && current != *attr; + prev = current, current = current->next); + + if (!current) + { + /* + * This is a serious error! + */ + + *attr = temp; + _cupsSetError(IPP_ERROR, _("IPP attribute is not a member of the message."), 1); + DEBUG_puts("4ipp_set_value: Unable to find attribute in message."); + return (NULL); + } + } + + if (prev) + prev->next = temp; + else + ipp->attrs = temp; + + ipp->current = temp; + ipp->prev = prev; + + if (ipp->last == *attr) + ipp->last = temp; + + *attr = temp; + } + + /* + * Return the value element... + */ + + return (temp->values + element); +} + + /* * 'ipp_write_file()' - Write IPP data to a file. */ @@ -3248,29 +5376,6 @@ ipp_write_file(int *fd, /* I - File descriptor */ } -#ifdef __linux -/* - * The following symbol definitions are provided only for KDE - * compatibility during the CUPS 1.2 testing period and will be - * removed in a future release of CUPS. These are PRIVATE APIs - * from CUPS 1.1.x that the KDE developers chose to use... - */ - -ipp_attribute_t * /* O - New attribute */ -_ipp_add_attr(ipp_t *ipp, /* I - IPP message */ - int num_values) /* I - Number of values */ -{ - return (_ippAddAttr(ipp, num_values)); -} - -void -_ipp_free_attr(ipp_attribute_t *attr) /* I - Attribute to free */ -{ - _ippFreeAttr(attr); -} -#endif /* __linux */ - - /* - * End of "$Id: ipp.c 7847 2008-08-19 04:22:14Z mike $". + * End of "$Id: ipp.c 10102 2011-11-02 23:52:39Z mike $". */ diff --git a/cups/ipp.h b/cups/ipp.h index 78e76fcba..2f29d59dc 100644 --- a/cups/ipp.h +++ b/cups/ipp.h @@ -63,54 +63,14 @@ extern "C" { * Types and structures... */ -typedef enum ipp_tag_e /**** Format tags for attributes ****/ +typedef enum ipp_dstate_e /**** Document states ****/ { - IPP_TAG_ZERO = 0x00, /* Zero tag - used for separators */ - IPP_TAG_OPERATION, /* Operation group */ - IPP_TAG_JOB, /* Job group */ - IPP_TAG_END, /* End-of-attributes */ - IPP_TAG_PRINTER, /* Printer group */ - IPP_TAG_UNSUPPORTED_GROUP, /* Unsupported attributes group */ - IPP_TAG_SUBSCRIPTION, /* Subscription group */ - IPP_TAG_EVENT_NOTIFICATION, /* Event group */ - IPP_TAG_DOCUMENT = 0x09, /* Document group */ - IPP_TAG_UNSUPPORTED_VALUE = 0x10, /* Unsupported value */ - IPP_TAG_DEFAULT, /* Default value */ - IPP_TAG_UNKNOWN, /* Unknown value */ - IPP_TAG_NOVALUE, /* No-value value */ - IPP_TAG_NOTSETTABLE = 0x15, /* Not-settable value */ - IPP_TAG_DELETEATTR, /* Delete-attribute value */ - IPP_TAG_ADMINDEFINE, /* Admin-defined value */ - IPP_TAG_INTEGER = 0x21, /* Integer value */ - IPP_TAG_BOOLEAN, /* Boolean value */ - IPP_TAG_ENUM, /* Enumeration value */ - IPP_TAG_STRING = 0x30, /* Octet string value */ - IPP_TAG_DATE, /* Date/time value */ - IPP_TAG_RESOLUTION, /* Resolution value */ - IPP_TAG_RANGE, /* Range value */ - IPP_TAG_BEGIN_COLLECTION, /* Beginning of collection value */ - IPP_TAG_TEXTLANG, /* Text-with-language value */ - IPP_TAG_NAMELANG, /* Name-with-language value */ - IPP_TAG_END_COLLECTION, /* End of collection value */ - IPP_TAG_TEXT = 0x41, /* Text value */ - IPP_TAG_NAME, /* Name value */ - IPP_TAG_RESERVED_STRING, /* Reserved for future string value @private@ */ - IPP_TAG_KEYWORD, /* Keyword value */ - IPP_TAG_URI, /* URI value */ - IPP_TAG_URISCHEME, /* URI scheme value */ - IPP_TAG_CHARSET, /* Character set value */ - IPP_TAG_LANGUAGE, /* Language value */ - IPP_TAG_MIMETYPE, /* MIME media type value */ - IPP_TAG_MEMBERNAME, /* Collection member name value */ - IPP_TAG_MASK = 0x7fffffff, /* Mask for copied attribute values */ - IPP_TAG_COPY = -0x7fffffff-1 /* Bitflag for copied attribute values */ -} ipp_tag_t; - -typedef enum ipp_res_e /**** Resolution units ****/ -{ - IPP_RES_PER_INCH = 3, /* Pixels per inch */ - IPP_RES_PER_CM /* Pixels per centimeter */ -} ipp_res_t; + IPP_DOCUMENT_PENDING = 3, + IPP_DOCUMENT_PROCESSING = 5, + IPP_DOCUMENT_CANCELED = 7, + IPP_DOCUMENT_ABORTED, + IPP_DOCUMENT_COMPLETED +} ipp_dstate_t; typedef enum ipp_finish_e /**** Finishings ****/ { @@ -141,23 +101,19 @@ typedef enum ipp_finish_e /**** Finishings ****/ IPP_FINISHINGS_BIND_LEFT = 50, /* Bind on left */ IPP_FINISHINGS_BIND_TOP, /* Bind on top */ IPP_FINISHINGS_BIND_RIGHT, /* Bind on right */ - IPP_FINISHINGS_BIND_BOTTOM /* Bind on bottom */ + IPP_FINISHINGS_BIND_BOTTOM, /* Bind on bottom */ + IPP_FINISHINGS_TRIM_AFTER_PAGES = 60, /* Trim output after each page */ + IPP_FINISHINGS_TRIM_AFTER_DOCUMENTS, /* Trim output after each document */ + IPP_FINISHINGS_TRIM_AFTER_COPIES, /* Trim output after each copy */ + IPP_FINISHINGS_TRIM_AFTER_JOB /* Trim output after job */ } ipp_finish_t; -typedef enum ipp_orient_e /**** Orientation values ****/ +typedef enum ipp_jcollate_e /**** Job collation types ****/ { - IPP_PORTRAIT = 3, /* No rotation */ - IPP_LANDSCAPE, /* 90 degrees counter-clockwise */ - IPP_REVERSE_LANDSCAPE, /* 90 degrees clockwise */ - IPP_REVERSE_PORTRAIT /* 180 degrees */ -} ipp_orient_t; - -typedef enum ipp_quality_e /**** Qualities ****/ -{ - IPP_QUALITY_DRAFT = 3, /* Draft quality */ - IPP_QUALITY_NORMAL, /* Normal quality */ - IPP_QUALITY_HIGH /* High quality */ -} ipp_quality_t; + IPP_JOB_UNCOLLATED_SHEETS = 3, + IPP_JOB_COLLATED_DOCUMENTS, + IPP_JOB_UNCOLLATED_DOCUMENTS +} ipp_jcollate_t; typedef enum ipp_jstate_e /**** Job states ****/ { @@ -168,24 +124,9 @@ typedef enum ipp_jstate_e /**** Job states ****/ IPP_JOB_CANCELED, /* Job has been canceled */ IPP_JOB_ABORTED, /* Job has aborted due to error */ IPP_JOB_COMPLETED /* Job has completed successfully */ -} ipp_jstate_t; + /* Legacy name for canceled state */ #define IPP_JOB_CANCELLED IPP_JOB_CANCELED - -typedef enum ipp_pstate_e /**** Printer states ****/ -{ - IPP_PRINTER_IDLE = 3, /* Printer is idle */ - IPP_PRINTER_PROCESSING, /* Printer is working */ - IPP_PRINTER_STOPPED /* Printer is stopped */ -} ipp_pstate_t; - -typedef enum ipp_state_e /**** IPP states ****/ -{ - IPP_ERROR = -1, /* An error occurred */ - IPP_IDLE, /* Nothing is happening/request completed */ - IPP_HEADER, /* The request header needs to be sent/received */ - IPP_ATTRIBUTE, /* One or more attributes need to be sent/received */ - IPP_DATA /* IPP request data needs to be sent/received */ -} ipp_state_t; +} ipp_jstate_t; typedef enum ipp_op_e /**** IPP operations ****/ { @@ -216,7 +157,10 @@ typedef enum ipp_op_e /**** IPP operations ****/ IPP_CANCEL_SUBSCRIPTION, /* Cancel a subscription @since CUPS 1.2/Mac OS X 10.5@ */ IPP_GET_NOTIFICATIONS, /* Get notification events @since CUPS 1.2/Mac OS X 10.5@ */ IPP_SEND_NOTIFICATIONS, /* Send notification events @private@ */ - IPP_GET_PRINT_SUPPORT_FILES = 0x0021, /* Get printer support files @private@ */ + IPP_GET_RESOURCE_ATTRIBUTES, /* Get resource attributes @private@ */ + IPP_GET_RESOURCE_DATA, /* Get resource data @private@ */ + IPP_GET_RESOURCES, /* Get list of resources @private@ */ + IPP_GET_PRINT_SUPPORT_FILES, /* Get printer support files @private@ */ IPP_ENABLE_PRINTER, /* Start a printer */ IPP_DISABLE_PRINTER, /* Stop a printer */ IPP_PAUSE_PRINTER_AFTER_CURRENT_JOB, /* Stop printer after the current job @private@ */ @@ -260,11 +204,48 @@ typedef enum ipp_op_e /**** IPP operations ****/ CUPS_AUTHENTICATE_JOB, /* Authenticate a job @since CUPS 1.2/Mac OS X 10.5@ */ CUPS_GET_PPD, /* Get a PPD file @since CUPS 1.3/Mac OS X 10.5@ */ CUPS_GET_DOCUMENT = 0x4027 /* Get a document file @since CUPS 1.4/Mac OS X 10.6@ */ -} ipp_op_t; -/* Old names for the operations */ + /* Legacy names for the add operations */ #define CUPS_ADD_PRINTER CUPS_ADD_MODIFY_PRINTER #define CUPS_ADD_CLASS CUPS_ADD_MODIFY_CLASS +} ipp_op_t; + +typedef enum ipp_orient_e /**** Orientation values ****/ +{ + IPP_PORTRAIT = 3, /* No rotation */ + IPP_LANDSCAPE, /* 90 degrees counter-clockwise */ + IPP_REVERSE_LANDSCAPE, /* 90 degrees clockwise */ + IPP_REVERSE_PORTRAIT /* 180 degrees */ +} ipp_orient_t; + +typedef enum ipp_pstate_e /**** Printer states ****/ +{ + IPP_PRINTER_IDLE = 3, /* Printer is idle */ + IPP_PRINTER_PROCESSING, /* Printer is working */ + IPP_PRINTER_STOPPED /* Printer is stopped */ +} ipp_pstate_t; + +typedef enum ipp_quality_e /**** Qualities ****/ +{ + IPP_QUALITY_DRAFT = 3, /* Draft quality */ + IPP_QUALITY_NORMAL, /* Normal quality */ + IPP_QUALITY_HIGH /* High quality */ +} ipp_quality_t; + +typedef enum ipp_res_e /**** Resolution units ****/ +{ + IPP_RES_PER_INCH = 3, /* Pixels per inch */ + IPP_RES_PER_CM /* Pixels per centimeter */ +} ipp_res_t; + +typedef enum ipp_state_e /**** IPP states ****/ +{ + IPP_ERROR = -1, /* An error occurred */ + IPP_IDLE, /* Nothing is happening/request completed */ + IPP_HEADER, /* The request header needs to be sent/received */ + IPP_ATTRIBUTE, /* One or more attributes need to be sent/received */ + IPP_DATA /* IPP request data needs to be sent/received */ +} ipp_state_t; typedef enum ipp_status_e /**** IPP status codes ****/ { @@ -272,9 +253,9 @@ typedef enum ipp_status_e /**** IPP status codes ****/ IPP_OK_SUBST, /* successful-ok-ignored-or-substituted-attributes */ IPP_OK_CONFLICT, /* successful-ok-conflicting-attributes */ IPP_OK_IGNORED_SUBSCRIPTIONS, /* successful-ok-ignored-subscriptions */ - IPP_OK_IGNORED_NOTIFICATIONS, /* successful-ok-ignored-notifications */ + IPP_OK_IGNORED_NOTIFICATIONS, /* successful-ok-ignored-notifications @private@ */ IPP_OK_TOO_MANY_EVENTS, /* successful-ok-too-many-events */ - IPP_OK_BUT_CANCEL_SUBSCRIPTION, /* successful-ok-but-cancel-subscription */ + IPP_OK_BUT_CANCEL_SUBSCRIPTION, /* successful-ok-but-cancel-subscription @private@ */ IPP_OK_EVENTS_COMPLETE, /* successful-ok-events-complete */ IPP_REDIRECTION_OTHER_SITE = 0x200, /* redirection-other-site @private@ */ CUPS_SEE_OTHER = 0x280, /* cups-see-other */ @@ -300,8 +281,12 @@ typedef enum ipp_status_e /**** IPP status codes ****/ IPP_ATTRIBUTES_NOT_SETTABLE, /* client-error-attributes-not-settable */ IPP_IGNORED_ALL_SUBSCRIPTIONS, /* client-error-ignored-all-subscriptions */ IPP_TOO_MANY_SUBSCRIPTIONS, /* client-error-too-many-subscriptions */ - IPP_IGNORED_ALL_NOTIFICATIONS, /* client-error-ignored-all-notifications */ - IPP_PRINT_SUPPORT_FILE_NOT_FOUND, /* client-error-print-support-file-not-found */ + IPP_IGNORED_ALL_NOTIFICATIONS, /* client-error-ignored-all-notifications @private@ */ + IPP_PRINT_SUPPORT_FILE_NOT_FOUND, /* client-error-print-support-file-not-found @private@ */ + IPP_DOCUMENT_PASSWORD_ERROR, /* client-error-document-password-error */ + IPP_DOCUMENT_PERMISSION_ERROR, /* client-error-document-permission-error */ + IPP_DOCUMENT_SECURITY_ERROR, /* client-error-document-security-error */ + IPP_DOCUMENT_UNPRINTABLE_ERROR, /* client-error-document-unprintable-error */ IPP_INTERNAL_ERROR = 0x0500, /* server-error-internal-error */ IPP_OPERATION_NOT_SUPPORTED, /* server-error-operation-not-supported */ @@ -314,116 +299,75 @@ typedef enum ipp_status_e /**** IPP status codes ****/ IPP_ERROR_JOB_CANCELED, /* server-error-job-canceled */ IPP_MULTIPLE_JOBS_NOT_SUPPORTED, /* server-error-multiple-document-jobs-not-supported */ IPP_PRINTER_IS_DEACTIVATED, /* server-error-printer-is-deactivated */ + IPP_TOO_MANY_JOBS, /* server-error-too-many-jobs */ + IPP_TOO_MANY_DOCUMENTS, /* server-error-too-many-documents */ IPP_AUTHENTICATION_CANCELED = 0x1000, /* Authentication canceled by user @since CUPS 1.5/Mac OS X 10.7@ */ IPP_PKI_ERROR, /* Error negotiating a secure connection @since CUPS 1.5/Mac OS X 10.7@ */ IPP_UPGRADE_REQUIRED /* TLS upgrade required */ -} ipp_status_t; -#define IPP_ERROR_JOB_CANCELLED IPP_ERROR_JOB_CANCELED -typedef unsigned char ipp_uchar_t; /**** Unsigned 8-bit integer/character ****/ - -/**** New in CUPS 1.2 ****/ -typedef ssize_t (*ipp_iocb_t)(void *, ipp_uchar_t *, size_t); - /**** IPP IO Callback Function @since CUPS 1.2/Mac OS X 10.5@ ****/ - -typedef union ipp_request_u /**** Request Header ****/ -{ - struct /* Any Header */ - { - ipp_uchar_t version[2]; /* Protocol version number */ - int op_status; /* Operation ID or status code*/ - int request_id; /* Request ID */ - } any; - - struct /* Operation Header */ - { - ipp_uchar_t version[2]; /* Protocol version number */ - ipp_op_t operation_id; /* Operation ID */ - int request_id; /* Request ID */ - } op; - - struct /* Status Header */ - { - ipp_uchar_t version[2]; /* Protocol version number */ - ipp_status_t status_code; /* Status code */ - int request_id; /* Request ID */ - } status; - - /**** New in CUPS 1.1.19 ****/ - struct /* Event Header @since CUPS 1.1.19/Mac OS X 10.3@ */ - { - ipp_uchar_t version[2]; /* Protocol version number */ - ipp_status_t status_code; /* Status code */ - int request_id; /* Request ID */ - } event; -} ipp_request_t; + /* Legacy name for canceled status */ +#define IPP_ERROR_JOB_CANCELLED IPP_ERROR_JOB_CANCELED -/**** New in CUPS 1.1.19 ****/ -typedef struct ipp_s ipp_t; +} ipp_status_t; -typedef union ipp_value_u /**** Attribute Value ****/ +typedef enum ipp_tag_e /**** Format tags for attributes ****/ { - int integer; /* Integer/enumerated value */ - - char boolean; /* Boolean value */ - - ipp_uchar_t date[11]; /* Date/time value */ - - struct - { - int xres, /* Horizontal resolution */ - yres; /* Vertical resolution */ - ipp_res_t units; /* Resolution units */ - } resolution; /* Resolution value */ - - struct - { - int lower, /* Lower value */ - upper; /* Upper value */ - } range; /* Range of integers value */ - - struct - { - char *charset; /* Character set */ - char *text; /* String */ - } string; /* String with language value */ - - struct - { - int length; /* Length of attribute */ - void *data; /* Data in attribute */ - } unknown; /* Unknown attribute type */ - -/**** New in CUPS 1.1.19 ****/ - ipp_t *collection; /* Collection value @since CUPS 1.1.19/Mac OS X 10.3@ */ -} ipp_value_t; + IPP_TAG_ZERO = 0x00, /* Zero tag - used for separators */ + IPP_TAG_OPERATION, /* Operation group */ + IPP_TAG_JOB, /* Job group */ + IPP_TAG_END, /* End-of-attributes */ + IPP_TAG_PRINTER, /* Printer group */ + IPP_TAG_UNSUPPORTED_GROUP, /* Unsupported attributes group */ + IPP_TAG_SUBSCRIPTION, /* Subscription group */ + IPP_TAG_EVENT_NOTIFICATION, /* Event group */ + IPP_TAG_RESOURCE, /* Resource group @private@ */ + IPP_TAG_DOCUMENT, /* Document group */ + IPP_TAG_UNSUPPORTED_VALUE = 0x10, /* Unsupported value */ + IPP_TAG_DEFAULT, /* Default value */ + IPP_TAG_UNKNOWN, /* Unknown value */ + IPP_TAG_NOVALUE, /* No-value value */ + IPP_TAG_NOTSETTABLE = 0x15, /* Not-settable value */ + IPP_TAG_DELETEATTR, /* Delete-attribute value */ + IPP_TAG_ADMINDEFINE, /* Admin-defined value */ + IPP_TAG_INTEGER = 0x21, /* Integer value */ + IPP_TAG_BOOLEAN, /* Boolean value */ + IPP_TAG_ENUM, /* Enumeration value */ + IPP_TAG_STRING = 0x30, /* Octet string value */ + IPP_TAG_DATE, /* Date/time value */ + IPP_TAG_RESOLUTION, /* Resolution value */ + IPP_TAG_RANGE, /* Range value */ + IPP_TAG_BEGIN_COLLECTION, /* Beginning of collection value */ + IPP_TAG_TEXTLANG, /* Text-with-language value */ + IPP_TAG_NAMELANG, /* Name-with-language value */ + IPP_TAG_END_COLLECTION, /* End of collection value */ + IPP_TAG_TEXT = 0x41, /* Text value */ + IPP_TAG_NAME, /* Name value */ + IPP_TAG_RESERVED_STRING, /* Reserved for future string value @private@ */ + IPP_TAG_KEYWORD, /* Keyword value */ + IPP_TAG_URI, /* URI value */ + IPP_TAG_URISCHEME, /* URI scheme value */ + IPP_TAG_CHARSET, /* Character set value */ + IPP_TAG_LANGUAGE, /* Language value */ + IPP_TAG_MIMETYPE, /* MIME media type value */ + IPP_TAG_MEMBERNAME, /* Collection member name value */ + IPP_TAG_EXTENSION = 0x7f, /* Extension point for 32-bit tags */ + IPP_TAG_MASK = 0x7fffffff, /* Mask for copied attribute values @private@ */ + /* The following expression is used to avoid compiler warnings with +/-0x80000000 */ + IPP_TAG_COPY = -0x7fffffff-1 /* Bitflag for copied attribute values @private@ */ +} ipp_tag_t; -typedef struct ipp_attribute_s /**** Attribute ****/ -{ - struct ipp_attribute_s *next; /* Next attribute in list */ - ipp_tag_t group_tag, /* Job/Printer/Operation group tag */ - value_tag; /* What type of value is it? */ - char *name; /* Name of attribute */ - int num_values; /* Number of values */ - ipp_value_t values[1]; /* Values */ -} ipp_attribute_t; - -struct ipp_s /**** IPP Request/Response/Notification ****/ -{ - ipp_state_t state; /* State of request */ - ipp_request_t request; /* Request header */ - ipp_attribute_t *attrs; /* Attributes */ - ipp_attribute_t *last; /* Last attribute in list */ - ipp_attribute_t *current; /* Current attribute (for read/write) */ - ipp_tag_t curtag; /* Current attribute group tag */ +typedef unsigned char ipp_uchar_t; /**** Unsigned 8-bit integer/character ****/ +typedef struct _ipp_s ipp_t; /**** IPP request/response data ****/ +typedef struct _ipp_attribute_s ipp_attribute_t; + /**** IPP attribute ****/ /**** New in CUPS 1.2 ****/ - ipp_attribute_t *prev; /* Previous attribute (for read) @since CUPS 1.2/Mac OS X 10.5@ */ +typedef ssize_t (*ipp_iocb_t)(void *context, ipp_uchar_t *buffer, size_t bytes); + /**** IPP IO Callback Function @since CUPS 1.2/Mac OS X 10.5@ ****/ -/**** New in CUPS 1.4.4 ****/ - int use; /* Use count @since CUPS 1.4.4/Mac OS X 10.6.?@ */ -}; +/**** New in CUPS 1.6 ****/ +typedef int (*ipp_copycb_t)(void *context, ipp_t *dst, ipp_attribute_t *attr); /* @@ -438,10 +382,10 @@ extern ipp_attribute_t *ippAddBooleans(ipp_t *ipp, ipp_tag_t group, extern ipp_attribute_t *ippAddDate(ipp_t *ipp, ipp_tag_t group, const char *name, const ipp_uchar_t *value); extern ipp_attribute_t *ippAddInteger(ipp_t *ipp, ipp_tag_t group, - ipp_tag_t type, const char *name, + ipp_tag_t value_tag, const char *name, int value); extern ipp_attribute_t *ippAddIntegers(ipp_t *ipp, ipp_tag_t group, - ipp_tag_t type, const char *name, + ipp_tag_t value_tag, const char *name, int num_values, const int *values); extern ipp_attribute_t *ippAddRange(ipp_t *ipp, ipp_tag_t group, const char *name, int lower, int upper); @@ -457,19 +401,19 @@ extern ipp_attribute_t *ippAddResolutions(ipp_t *ipp, ipp_tag_t group, const int *yres); extern ipp_attribute_t *ippAddSeparator(ipp_t *ipp); extern ipp_attribute_t *ippAddString(ipp_t *ipp, ipp_tag_t group, - ipp_tag_t type, const char *name, - const char *charset, const char *value); + ipp_tag_t value_tag, const char *name, + const char *language, const char *value); extern ipp_attribute_t *ippAddStrings(ipp_t *ipp, ipp_tag_t group, - ipp_tag_t type, const char *name, - int num_values, const char *charset, + ipp_tag_t value_tag, const char *name, + int num_values, const char *language, const char * const *values); extern time_t ippDateToTime(const ipp_uchar_t *date); extern void ippDelete(ipp_t *ipp); extern const char *ippErrorString(ipp_status_t error); extern ipp_attribute_t *ippFindAttribute(ipp_t *ipp, const char *name, - ipp_tag_t type); + ipp_tag_t value_tag); extern ipp_attribute_t *ippFindNextAttribute(ipp_t *ipp, const char *name, - ipp_tag_t type); + ipp_tag_t value_tag); extern size_t ippLength(ipp_t *ipp); extern ipp_t *ippNew(void); extern ipp_state_t ippRead(http_t *http, ipp_t *ipp); @@ -488,7 +432,7 @@ extern void ippDeleteAttribute(ipp_t *ipp, ipp_attribute_t *attr) _CUPS_API_1_1 extern ipp_state_t ippReadFile(int fd, ipp_t *ipp) _CUPS_API_1_1_19; extern ipp_state_t ippWriteFile(int fd, ipp_t *ipp) _CUPS_API_1_1_19; -/**** New in CUPS 1.2 ****/ +/**** New in CUPS 1.2/Mac OS X 10.5 ****/ extern ipp_attribute_t *ippAddOctetString(ipp_t *ipp, ipp_tag_t group, const char *name, const void *data, int datalen) _CUPS_API_1_2; @@ -501,10 +445,70 @@ extern ipp_state_t ippReadIO(void *src, ipp_iocb_t cb, int blocking, extern ipp_state_t ippWriteIO(void *dst, ipp_iocb_t cb, int blocking, ipp_t *parent, ipp_t *ipp) _CUPS_API_1_2; -/**** New in CUPS 1.4 ****/ +/**** New in CUPS 1.4/Mac OS X 10.6 ****/ extern const char *ippTagString(ipp_tag_t tag) _CUPS_API_1_4; extern ipp_tag_t ippTagValue(const char *name) _CUPS_API_1_4; +/**** New in CUPS 1.6 ****/ +extern ipp_attribute_t *ippAddOutOfBand(ipp_t *ipp, ipp_tag_t group, ipp_tag_t value_tag, + const char *name); +extern size_t ippAttributeString(ipp_attribute_t *attr, char *buffer, + size_t bufsize) _CUPS_API_1_6; +extern ipp_attribute_t *ippCopyAttribute(ipp_t *dst, ipp_attribute_t *attr, + int quickcopy) _CUPS_API_1_6; +extern int ippCopyAttributes(ipp_t *dst, ipp_t *src, + int quickcopy, ipp_copycb_t cb, void *context) + _CUPS_API_1_6; +extern int ippDeleteValues(ipp_t *ipp, ipp_attribute_t *attr, int element, + int count) _CUPS_API_1_6; +extern const char *ippEnumString(const char *attrname, int enumvalue) _CUPS_API_1_6; +extern int ippEnumValue(const char *attrname, const char *enumstring) + _CUPS_API_1_6; +extern ipp_attribute_t *ippFirstAttribute(ipp_t *ipp) _CUPS_API_1_6; +extern int ippGetBoolean(ipp_attribute_t *attr, int element) + _CUPS_API_1_6; +extern ipp_t *ippGetCollection(ipp_attribute_t *attr, + int element) _CUPS_API_1_6; +extern int ippGetCount(ipp_attribute_t *attr) _CUPS_API_1_6; +extern ipp_tag_t ippGetGroupTag(ipp_attribute_t *attr) _CUPS_API_1_6; +extern int ippGetInteger(ipp_attribute_t *attr, int element) + _CUPS_API_1_6; +extern const char *ippGetName(ipp_attribute_t *attr) _CUPS_API_1_6; +extern ipp_op_t ippGetOperation(ipp_t *ipp) _CUPS_API_1_6; +extern int ippGetRequestId(ipp_t *ipp) _CUPS_API_1_6; +extern int ippGetResolution(ipp_attribute_t *attr, int element, + int *yres, ipp_res_t *units) _CUPS_API_1_6; +extern ipp_status_t ippGetStatusCode(ipp_t *ipp) _CUPS_API_1_6; +extern const char *ippGetString(ipp_attribute_t *attr, int element, + const char **language) _CUPS_API_1_6; +extern ipp_tag_t ippGetValueTag(ipp_attribute_t *attr) _CUPS_API_1_6; +extern int ippGetVersion(ipp_t *ipp, int *minor) _CUPS_API_1_6; +extern ipp_attribute_t *ippNextAttribute(ipp_t *ipp) _CUPS_API_1_6; +extern int ippSetBoolean(ipp_t *ipp, ipp_attribute_t **attr, + int element, int boolvalue) _CUPS_API_1_6; +extern int ippSetCollection(ipp_t *ipp, ipp_attribute_t **attr, + int element, ipp_t *colvalue) _CUPS_API_1_6; +extern int ippSetGroupTag(ipp_t *ipp, ipp_attribute_t **attr, + ipp_tag_t group_tag) _CUPS_API_1_6; +extern int ippSetInteger(ipp_t *ipp, ipp_attribute_t **attr, + int element, int intvalue) _CUPS_API_1_6; +extern int ippSetName(ipp_t *ipp, ipp_attribute_t **attr, const char *name) + _CUPS_API_1_6; +extern int ippSetOperation(ipp_t *ipp, ipp_op_t op) _CUPS_API_1_6; +extern int ippSetRange(ipp_t *ipp, ipp_attribute_t **attr, int element, + int lowervalue, int uppervalue) _CUPS_API_1_6; +extern int ippSetRequestId(ipp_t *ipp, int request_id) + _CUPS_API_1_6; +extern int ippSetResolution(ipp_t *ipp, ipp_attribute_t **attr, + int element, ipp_res_t unitsvalue, + int xresvalue, int yresvalue) _CUPS_API_1_6; +extern int ippSetStatusCode(ipp_t *ipp, ipp_status_t status) _CUPS_API_1_6; +extern int ippSetString(ipp_t *ipp, ipp_attribute_t **attr, + int element, const char *strvalue) _CUPS_API_1_6; +extern int ippSetValueTag(ipp_t *ipp, ipp_attribute_t **attr, + ipp_tag_t value_tag) _CUPS_API_1_6; +extern int ippSetVersion(ipp_t *ipp, int major, int minor) _CUPS_API_1_6; + /* * C++ magic... diff --git a/cups/language.c b/cups/language.c index 46808ed92..e0188c6cb 100644 --- a/cups/language.c +++ b/cups/language.c @@ -80,7 +80,7 @@ static const char * const lang_encodings[] = "cp1256", "cp1257", "cp1258", "koi8-r", "koi8-u", "iso-8859-11", - "iso-8859-16", "mac-roman", + "iso-8859-16", "mac", "unknown", "unknown", "unknown", "unknown", "unknown", "unknown", diff --git a/cups/libcups_s.exp b/cups/libcups_s.exp index 4d095537a..f500e7712 100644 --- a/cups/libcups_s.exp +++ b/cups/libcups_s.exp @@ -50,9 +50,7 @@ _httpPeek _httpResolveURI _httpSetTimeout _httpWait -_ippAddAttr _ippFindOption -_ippFreeAttr _ppdFreeLanguages _ppdGetEncoding _ppdGetLanguages diff --git a/cups/ppd-cache.c b/cups/ppd-cache.c index e161d057a..c40214823 100644 --- a/cups/ppd-cache.c +++ b/cups/ppd-cache.c @@ -1271,7 +1271,8 @@ _ppdCacheCreateWithPPD(ppd_file_t *ppd) /* I - PPD file */ if (filter) cupsArrayAdd(pc->filters, - "application/vnd.cups-command application/postscript 0 -"); + "application/vnd.cups-command application/postscript 100 " + "commandtops"); } if ((ppd_attr = ppdFindAttr(ppd, "cupsPreFilter", NULL)) != NULL) diff --git a/cups/ppd.h b/cups/ppd.h index f66036f9a..276b47bd5 100644 --- a/cups/ppd.h +++ b/cups/ppd.h @@ -3,6 +3,10 @@ * * PostScript Printer Description definitions for CUPS. * + * THESE APIS ARE DEPRECATED. TO COMPILE WITHOUT WARNINGS ADD + * "-D_PPD_DEPRECATED" TO YOUR COMPILE OPTIONS. THIS HEADER AND THESE + * FUNCTIONS WILL BE REMOVED IN A FUTURE RELEASE OF CUPS. + * * Copyright 2007-2011 by Apple Inc. * Copyright 1997-2007 by Easy Software Products, all rights reserved. * @@ -46,6 +50,16 @@ extern "C" { # endif /* __cplusplus */ +/* + * Define _PPD_DEPRECATED to silence the warnings about PPD functions being + * deprecated... + */ + +# ifndef _PPD_DEPRECATED +# define _PPD_DEPRECATED _CUPS_DEPRECATED +# endif /* !_PPD_DEPRECATED */ + + /* * PPD version... */ @@ -361,7 +375,8 @@ extern int ppdEmitFd(ppd_file_t *ppd, int fd, extern int ppdEmitJCL(ppd_file_t *ppd, FILE *fp, int job_id, const char *user, const char *title); extern ppd_choice_t *ppdFindChoice(ppd_option_t *o, const char *option); -extern ppd_choice_t *ppdFindMarkedChoice(ppd_file_t *ppd, const char *keyword); +extern ppd_choice_t *ppdFindMarkedChoice(ppd_file_t *ppd, + const char *keyword); extern ppd_option_t *ppdFindOption(ppd_file_t *ppd, const char *keyword); extern int ppdIsMarked(ppd_file_t *ppd, const char *keyword, const char *option); @@ -376,64 +391,67 @@ extern ppd_size_t *ppdPageSize(ppd_file_t *ppd, const char *name); extern float ppdPageWidth(ppd_file_t *ppd, const char *name); /**** New in CUPS 1.1.19 ****/ -extern const char *ppdErrorString(ppd_status_t status) _CUPS_API_1_1_19; +extern const char *ppdErrorString(ppd_status_t status) _PPD_DEPRECATED; extern ppd_attr_t *ppdFindAttr(ppd_file_t *ppd, const char *name, - const char *spec) _CUPS_API_1_1_19; + const char *spec) _PPD_DEPRECATED; extern ppd_attr_t *ppdFindNextAttr(ppd_file_t *ppd, const char *name, - const char *spec) _CUPS_API_1_1_19; -extern ppd_status_t ppdLastError(int *line) _CUPS_API_1_1_19; + const char *spec) _PPD_DEPRECATED; +extern ppd_status_t ppdLastError(int *line) _PPD_DEPRECATED; /**** New in CUPS 1.1.20 ****/ -extern void ppdSetConformance(ppd_conform_t c) _CUPS_API_1_1_20; +extern void ppdSetConformance(ppd_conform_t c) _PPD_DEPRECATED; /**** New in CUPS 1.2 ****/ extern int ppdCollect2(ppd_file_t *ppd, ppd_section_t section, - float min_order, ppd_choice_t ***choices) _CUPS_API_1_2; + float min_order, ppd_choice_t ***choices) + _PPD_DEPRECATED; extern int ppdEmitAfterOrder(ppd_file_t *ppd, FILE *fp, ppd_section_t section, int limit, - float min_order) _CUPS_API_1_2; -extern int ppdEmitJCLEnd(ppd_file_t *ppd, FILE *fp) _CUPS_API_1_2; + float min_order) _PPD_DEPRECATED; +extern int ppdEmitJCLEnd(ppd_file_t *ppd, FILE *fp) _PPD_DEPRECATED; extern char *ppdEmitString(ppd_file_t *ppd, ppd_section_t section, - float min_order) _CUPS_API_1_2; + float min_order) _PPD_DEPRECATED; extern ppd_coption_t *ppdFindCustomOption(ppd_file_t *ppd, - const char *keyword) _CUPS_API_1_2; + const char *keyword) _PPD_DEPRECATED; extern ppd_cparam_t *ppdFindCustomParam(ppd_coption_t *opt, - const char *name) _CUPS_API_1_2; -extern ppd_cparam_t *ppdFirstCustomParam(ppd_coption_t *opt) _CUPS_API_1_2; -extern ppd_option_t *ppdFirstOption(ppd_file_t *ppd) _CUPS_API_1_2; -extern ppd_cparam_t *ppdNextCustomParam(ppd_coption_t *opt) _CUPS_API_1_2; -extern ppd_option_t *ppdNextOption(ppd_file_t *ppd) _CUPS_API_1_2; -extern int ppdLocalize(ppd_file_t *ppd) _CUPS_API_1_2; -extern ppd_file_t *ppdOpen2(cups_file_t *fp) _CUPS_API_1_2; + const char *name) _PPD_DEPRECATED; +extern ppd_cparam_t *ppdFirstCustomParam(ppd_coption_t *opt) _PPD_DEPRECATED; +extern ppd_option_t *ppdFirstOption(ppd_file_t *ppd) _PPD_DEPRECATED; +extern ppd_cparam_t *ppdNextCustomParam(ppd_coption_t *opt) _PPD_DEPRECATED; +extern ppd_option_t *ppdNextOption(ppd_file_t *ppd) _PPD_DEPRECATED; +extern int ppdLocalize(ppd_file_t *ppd) _PPD_DEPRECATED; +extern ppd_file_t *ppdOpen2(cups_file_t *fp) _PPD_DEPRECATED; /**** New in CUPS 1.3/Mac OS X 10.5 ****/ extern const char *ppdLocalizeIPPReason(ppd_file_t *ppd, const char *reason, const char *scheme, char *buffer, - size_t bufsize) _CUPS_API_1_3; + size_t bufsize) _PPD_DEPRECATED; /**** New in CUPS 1.4/Mac OS X 10.6 ****/ extern int cupsGetConflicts(ppd_file_t *ppd, const char *option, const char *choice, cups_option_t **options) - _CUPS_API_1_4; -extern int cupsResolveConflicts(ppd_file_t *ppd, const char *option, + _PPD_DEPRECATED; +extern int cupsResolveConflicts(ppd_file_t *ppd, + const char *option, const char *choice, int *num_options, cups_option_t **options) - _CUPS_API_1_4; + _PPD_DEPRECATED; extern int ppdInstallableConflict(ppd_file_t *ppd, const char *option, const char *choice) - _CUPS_API_1_4; + _PPD_DEPRECATED; extern ppd_attr_t *ppdLocalizeAttr(ppd_file_t *ppd, const char *keyword, - const char *spec) _CUPS_API_1_4; + const char *spec) _PPD_DEPRECATED; extern const char *ppdLocalizeMarkerName(ppd_file_t *ppd, - const char *name) _CUPS_API_1_4; + const char *name) + _PPD_DEPRECATED; extern int ppdPageSizeLimits(ppd_file_t *ppd, ppd_size_t *minimum, - ppd_size_t *maximum) _CUPS_API_1_4; + ppd_size_t *maximum) _PPD_DEPRECATED; /* diff --git a/cups/pwg-media.c b/cups/pwg-media.c index 5c7ca2397..7cc55b44b 100644 --- a/cups/pwg-media.c +++ b/cups/pwg-media.c @@ -103,8 +103,8 @@ static _pwg_media_t const cups_pwg_media[] = _PWG_MEDIA_IN("na_eur-edp_12x14in", NULL, NULL, 12, 14), _PWG_MEDIA_IN("na_arch-b_12x18in", "arch-b", "ARCHB", 12, 18), _PWG_MEDIA_IN("na_12x19_12x19in", NULL, "12x19", 12, 19), - _PWG_MEDIA_IN("na_b-plus_12x19.17in", NULL, NULL, 12, 19.17), - _PWG_MEDIA_IN("na_super-b_13x19in", "super-b", "SuperB", 13, 19), + _PWG_MEDIA_IN("na_b-plus_12x19.17in", NULL, "SuperB", 12, 19.17), + _PWG_MEDIA_IN("na_super-b_13x19in", "super-b", "13x19", 13, 19), _PWG_MEDIA_IN("na_c_17x22in", "c", "AnsiC", 17, 22), _PWG_MEDIA_IN("na_arch-c_18x24in", "arch-c", "ARCHC", 18, 24), _PWG_MEDIA_IN("na_d_22x34in", "d", "AnsiD", 22, 34), diff --git a/cups/testipp.c b/cups/testipp.c index efe2174f1..70c83bf4b 100644 --- a/cups/testipp.c +++ b/cups/testipp.c @@ -758,7 +758,7 @@ print_attributes(ipp_t *ipp, /* I - IPP request */ int i; /* Looping var */ ipp_tag_t group; /* Current group */ ipp_attribute_t *attr; /* Current attribute */ - ipp_value_t *val; /* Current value */ + _ipp_value_t *val; /* Current value */ static const char * const tags[] = /* Value/group tag strings */ { "reserved-00", diff --git a/cups/versioning.h b/cups/versioning.h index 719483dd7..6881ec79d 100644 --- a/cups/versioning.h +++ b/cups/versioning.h @@ -75,11 +75,11 @@ * a warning at compile-time. */ -# if defined(__GNUC__) && __GNUC__ > 2 +# if defined(__GNUC__) && __GNUC__ > 2 && !defined(_CUPS_SOURCE) # define _CUPS_DEPRECATED __attribute__ ((__deprecated__)) # else # define _CUPS_DEPRECATED -# endif /* __GNUC__ && __GNUC__ > 2 */ +# endif /* __GNUC__ && __GNUC__ > 2 && !_CUPS_SOURCE */ # ifndef __GNUC__ # define __attribute__(x) diff --git a/doc/help/api-httpipp.html b/doc/help/api-httpipp.html index d540b8ed3..b0f94ecba 100644 --- a/doc/help/api-httpipp.html +++ b/doc/help/api-httpipp.html @@ -448,9 +448,11 @@ address records for the specified name.">httpGetHostByName content-length or transfer-encoding fields.">httpGetLength

  • httpGetLength2
  • +
  • httpGetState
  • httpGetStatus
  • httpGetSubField
  • httpGetSubField2
  • +
  • httpGetVersion
  • httpGets
  • httpHead
  • httpSetCredentials
  • ippAddInteger
  • ippAddIntegers
  • ippAddOctetString
  • +
  • ippAddOutOfBand
  • ippAddRange
  • ippAddRanges
  • ippAddResolution
  • @@ -501,24 +504,58 @@ connection.">httpSetCredentials
  • ippAddSeparator
  • ippAddString
  • ippAddStrings
  • +
  • ippAttributeString
  • +
  • ippCopyAttribute
  • +
  • ippCopyAttributes
  • ippDateToTime
  • ippDelete
  • ippDeleteAttribute
  • +
  • ippDeleteValues
  • +
  • ippEnumString
  • +
  • ippEnumValue
  • ippErrorString
  • ippErrorValue
  • ippFindAttribute
  • ippFindNextAttribute
  • +
  • ippFirstAttribute
  • +
  • ippGetBoolean
  • +
  • ippGetCollection
  • +
  • ippGetCount
  • +
  • ippGetGroupTag
  • +
  • ippGetInteger
  • +
  • ippGetName
  • +
  • ippGetOperation
  • +
  • ippGetRequestId
  • +
  • ippGetResolution
  • +
  • ippGetStatusCode
  • +
  • ippGetString
  • +
  • ippGetValueTag
  • +
  • ippGetVersion
  • ippLength
  • ippNew
  • ippNewRequest
  • +
  • ippNextAttribute
  • ippOpString
  • ippOpValue
  • ippPort
  • ippRead
  • ippReadFile
  • ippReadIO
  • +
  • ippSetBoolean
  • +
  • ippSetCollection
  • +
  • ippSetGroupTag
  • +
  • ippSetInteger
  • +
  • ippSetName
  • +
  • ippSetOperation
  • ippSetPort
  • +
  • ippSetRange
  • +
  • ippSetRequestId
  • +
  • ippSetResolution
  • +
  • ippSetStatusCode
  • +
  • ippSetString
  • +
  • ippSetValueTag
  • +
  • ippSetVersion
  • ippTagString
  • ippTagValue
  • ippTimeToDate
  • @@ -550,21 +587,19 @@ are server-oriented...">http_state_t
  • http_uri_coding_t
  • http_uri_status_t
  • http_version_t
  • -
  • ipp_attribute_t
  • +
  • ipp_attribute_t
  • +
  • ipp_copycb_t
  • +
  • ipp_dstate_t
  • ipp_finish_t
  • ipp_iocb_t
  • -
  • ipp_jstate_t
  • -
  • ipp_op_t
  • +
  • ipp_jcollate_t
  • ipp_orient_t
  • ipp_pstate_t
  • ipp_quality_t
  • -
  • ipp_request_t
  • ipp_res_t
  • ipp_state_t
  • -
  • ipp_t
  • -
  • ipp_uchar_t
  • -
  • ipp_tag_t
  • -
  • ipp_value_t
  • +
  • ipp_t
  • +
  • ipp_uchar_t
  • Structures
  • -
  • Unions
  • Constants
    • http_auth_e
    • @@ -592,7 +621,9 @@ are server-oriented...">http_state_e
    • http_uri_coding_e
    • http_uri_status_e
    • http_version_e
    • +
    • ipp_dstate_e
    • ipp_finish_e
    • +
    • ipp_jcollate_e
    • ipp_jstate_e
    • ipp_op_e
    • ipp_orient_e
    • @@ -1066,7 +1097,7 @@ void cupsEncodeOptions2 (
          ipp_t *ipp,
          int num_options,
          cups_option_t *options,
      -    ipp_tag_t group_tag
      +    ipp_tag_t group_tag
      );

      Parameters

      @@ -1186,7 +1217,8 @@ the request respectively.

      Discussion

      Use this function to get the response for an IPP request sent using cupsSendDocument() or cupsSendRequest(). For requests that return -additional data, use httpRead() after getting a successful response. +additional data, use httpRead() after getting a successful response, +otherwise call httpFlush() to complete the response processing.

      cupsLastError

      @@ -2026,6 +2058,19 @@ off_t httpGetLength2 (
      content larger than 2^31 - 1.

      +

      httpGetState

      +

      Get the current state of the HTTP request.

      +

      +http_state_t httpGetState (
      +    http_t *http
      +);

      +

      Parameters

      +
      +
      http
      +
      Connection to server
      +
      +

      Return Value

      +

      HTTP state

       CUPS 1.2/Mac OS X 10.5 httpGetStatus

      Get the status of the last HTTP request.

      @@ -2086,6 +2131,19 @@ char *httpGetSubField2 (

      Return Value

      Value or NULL

      +

      httpGetVersion

      +

      Get the HTTP version at the other end.

      +

      +http_version_t httpGetVersion (
      +    http_t *http
      +);

      +

      Parameters

      +
      +
      http
      +
      Connection to server
      +
      +

      Return Value

      +

      Version number

      httpGets

      Get a line of text from a HTTP connection.

      @@ -2650,7 +2708,7 @@ ssize_t httpWrite2 (

      ipp_attribute_t *ippAddBoolean (
          ipp_t *ipp,
      -    ipp_tag_t group,
      +    ipp_tag_t group,
          const char *name,
          char value
      );

      @@ -2667,12 +2725,21 @@ ssize_t httpWrite2 (

      Return Value

      New attribute

      +

      Discussion

      +

      The ipp parameter refers to an IPP message previously created using the +ippNew or ippNewRequest functions.
      +
      +The group parameter specifies the IPP attribute group tag: none +(IPP_TAG_ZERO, for member attributes), document (IPP_TAG_DOCUMENT), +event notification (IPP_TAG_EVENT_NOTIFICATION), operation +(IPP_TAG_OPERATION), printer (IPP_TAG_PRINTER), subscription +(IPP_TAG_SUBSCRIPTION), or unsupported (IPP_TAG_UNSUPPORTED_GROUP).

      ippAddBooleans

      Add an array of boolean values.

      ipp_attribute_t *ippAddBooleans (
          ipp_t *ipp,
      -    ipp_tag_t group,
      +    ipp_tag_t group,
          const char *name,
          int num_values,
          const char *values
      @@ -2692,12 +2759,21 @@ ssize_t httpWrite2 (

      Return Value

      New attribute

      +

      Discussion

      +

      The ipp parameter refers to an IPP message previously created using the +ippNew or ippNewRequest functions.
      +
      +The group parameter specifies the IPP attribute group tag: none +(IPP_TAG_ZERO, for member attributes), document (IPP_TAG_DOCUMENT), +event notification (IPP_TAG_EVENT_NOTIFICATION), operation +(IPP_TAG_OPERATION), printer (IPP_TAG_PRINTER), subscription +(IPP_TAG_SUBSCRIPTION), or unsupported (IPP_TAG_UNSUPPORTED_GROUP).

       CUPS 1.1.19/Mac OS X 10.3 ippAddCollection

      Add a collection value.

      ipp_attribute_t *ippAddCollection (
          ipp_t *ipp,
      -    ipp_tag_t group,
      +    ipp_tag_t group,
          const char *name,
          ipp_t *value
      );

      @@ -2714,12 +2790,23 @@ ssize_t httpWrite2 (

      Return Value

      New attribute

      +

      Discussion

      +

      The ipp parameter refers to an IPP message previously created using the +ippNew or ippNewRequest functions.
      +
      +The group parameter specifies the IPP attribute group tag: none +(IPP_TAG_ZERO, for member attributes), document (IPP_TAG_DOCUMENT), +event notification (IPP_TAG_EVENT_NOTIFICATION), operation +(IPP_TAG_OPERATION), printer (IPP_TAG_PRINTER), subscription +(IPP_TAG_SUBSCRIPTION), or unsupported (IPP_TAG_UNSUPPORTED_GROUP). + +

       CUPS 1.1.19/Mac OS X 10.3 ippAddCollections

      Add an array of collection values.

      ipp_attribute_t *ippAddCollections (
          ipp_t *ipp,
      -    ipp_tag_t group,
      +    ipp_tag_t group,
          const char *name,
          int num_values,
          const ipp_t **values
      @@ -2739,12 +2826,23 @@ ssize_t httpWrite2 (

      Return Value

      New attribute

      +

      Discussion

      +

      The ipp parameter refers to an IPP message previously created using the +ippNew or ippNewRequest functions.
      +
      +The group parameter specifies the IPP attribute group tag: none +(IPP_TAG_ZERO, for member attributes), document (IPP_TAG_DOCUMENT), +event notification (IPP_TAG_EVENT_NOTIFICATION), operation +(IPP_TAG_OPERATION), printer (IPP_TAG_PRINTER), subscription +(IPP_TAG_SUBSCRIPTION), or unsupported (IPP_TAG_UNSUPPORTED_GROUP). + +

      ippAddDate

      Add a date attribute to an IPP message.

      ipp_attribute_t *ippAddDate (
          ipp_t *ipp,
      -    ipp_tag_t group,
      +    ipp_tag_t group,
          const char *name,
          const ipp_uchar_t *value
      );

      @@ -2761,13 +2859,22 @@ ssize_t httpWrite2 (

      Return Value

      New attribute

      +

      Discussion

      +

      The ipp parameter refers to an IPP message previously created using the +ippNew or ippNewRequest functions.
      +
      +The group parameter specifies the IPP attribute group tag: none +(IPP_TAG_ZERO, for member attributes), document (IPP_TAG_DOCUMENT), +event notification (IPP_TAG_EVENT_NOTIFICATION), operation +(IPP_TAG_OPERATION), printer (IPP_TAG_PRINTER), subscription +(IPP_TAG_SUBSCRIPTION), or unsupported (IPP_TAG_UNSUPPORTED_GROUP).

      ippAddInteger

      Add a integer attribute to an IPP message.

      ipp_attribute_t *ippAddInteger (
          ipp_t *ipp,
      -    ipp_tag_t group,
      -    ipp_tag_t type,
      +    ipp_tag_t group,
      +    ipp_tag_t value_tag,
          const char *name,
          int value
      );

      @@ -2777,7 +2884,7 @@ ssize_t httpWrite2 (
      IPP message
      group
      IPP group
      -
      type
      +
      value_tag
      Type of attribute
      name
      Name of attribute
      @@ -2786,13 +2893,25 @@ ssize_t httpWrite2 (

      Return Value

      New attribute

      +

      Discussion

      +

      The ipp parameter refers to an IPP message previously created using the +ippNew or ippNewRequest functions.
      +
      +The group parameter specifies the IPP attribute group tag: none +(IPP_TAG_ZERO, for member attributes), document (IPP_TAG_DOCUMENT), +event notification (IPP_TAG_EVENT_NOTIFICATION), operation +(IPP_TAG_OPERATION), printer (IPP_TAG_PRINTER), subscription +(IPP_TAG_SUBSCRIPTION), or unsupported (IPP_TAG_UNSUPPORTED_GROUP).
      +
      +Supported values include enum (IPP_TAG_ENUM) and integer +(IPP_TAG_INTEGER).

      ippAddIntegers

      Add an array of integer values.

      ipp_attribute_t *ippAddIntegers (
          ipp_t *ipp,
      -    ipp_tag_t group,
      -    ipp_tag_t type,
      +    ipp_tag_t group,
      +    ipp_tag_t value_tag,
          const char *name,
          int num_values,
          const int *values
      @@ -2803,7 +2922,7 @@ ssize_t httpWrite2 (

      IPP message
      group
      IPP group
      -
      type
      +
      value_tag
      Type of attribute
      name
      Name of attribute
      @@ -2814,12 +2933,24 @@ ssize_t httpWrite2 (

      Return Value

      New attribute

      +

      Discussion

      +

      The ipp parameter refers to an IPP message previously created using the +ippNew or ippNewRequest functions.
      +
      +The group parameter specifies the IPP attribute group tag: none +(IPP_TAG_ZERO, for member attributes), document (IPP_TAG_DOCUMENT), +event notification (IPP_TAG_EVENT_NOTIFICATION), operation +(IPP_TAG_OPERATION), printer (IPP_TAG_PRINTER), subscription +(IPP_TAG_SUBSCRIPTION), or unsupported (IPP_TAG_UNSUPPORTED_GROUP).
      +
      +Supported values include enum (IPP_TAG_ENUM) and integer +(IPP_TAG_INTEGER).

       CUPS 1.2/Mac OS X 10.5 ippAddOctetString

      Add an octetString value to an IPP message.

      ipp_attribute_t *ippAddOctetString (
          ipp_t *ipp,
      -    ipp_tag_t group,
      +    ipp_tag_t group,
          const char *name,
          const void *data,
          int datalen
      @@ -2839,12 +2970,62 @@ ssize_t httpWrite2 (

      Return Value

      New attribute

      +

      Discussion

      +

      The ipp parameter refers to an IPP message previously created using the +ippNew or ippNewRequest functions.
      +
      +The group parameter specifies the IPP attribute group tag: none +(IPP_TAG_ZERO, for member attributes), document (IPP_TAG_DOCUMENT), +event notification (IPP_TAG_EVENT_NOTIFICATION), operation +(IPP_TAG_OPERATION), printer (IPP_TAG_PRINTER), subscription +(IPP_TAG_SUBSCRIPTION), or unsupported (IPP_TAG_UNSUPPORTED_GROUP). + +

      +

       CUPS 1.6 ippAddOutOfBand

      +

      Add an out-of-band value to an IPP message.

      +

      +ipp_attribute_t *ippAddOutOfBand (
      +    ipp_t *ipp,
      +    ipp_tag_t group,
      +    ipp_tag_t value_tag,
      +    const char *name
      +);

      +

      Parameters

      +
      +
      ipp
      +
      IPP message
      +
      group
      +
      IPP group
      +
      value_tag
      +
      Type of attribute
      +
      name
      +
      Name of attribute
      +
      +

      Return Value

      +

      New attribute

      +

      Discussion

      +

      The ipp parameter refers to an IPP message previously created using the +ippNew or ippNewRequest functions.
      +
      +The group parameter specifies the IPP attribute group tag: none +(IPP_TAG_ZERO, for member attributes), document (IPP_TAG_DOCUMENT), +event notification (IPP_TAG_EVENT_NOTIFICATION), operation +(IPP_TAG_OPERATION), printer (IPP_TAG_PRINTER), subscription +(IPP_TAG_SUBSCRIPTION), or unsupported (IPP_TAG_UNSUPPORTED_GROUP).
      +
      +Supported out-of-band values include unsupported-value +(IPP_TAG_UNSUPPORTED_VALUE), default (IPP_TAG_DEFAULT), unknown +(IPP_TAG_UNKNOWN), no-value (IPP_TAG_NOVALUE), not-settable +(IPP_TAG_NOTSETTABLE), delete-attribute (IPP_TAG_DELETEATTR), and +admin-define (IPP_TAG_ADMINDEFINE). + +

      ippAddRange

      Add a range of values to an IPP message.

      ipp_attribute_t *ippAddRange (
          ipp_t *ipp,
      -    ipp_tag_t group,
      +    ipp_tag_t group,
          const char *name,
          int lower,
          int upper
      @@ -2864,12 +3045,23 @@ ssize_t httpWrite2 (

      Return Value

      New attribute

      +

      Discussion

      +

      The ipp parameter refers to an IPP message previously created using the +ippNew or ippNewRequest functions.
      +
      +The group parameter specifies the IPP attribute group tag: none +(IPP_TAG_ZERO, for member attributes), document (IPP_TAG_DOCUMENT), +event notification (IPP_TAG_EVENT_NOTIFICATION), operation +(IPP_TAG_OPERATION), printer (IPP_TAG_PRINTER), subscription +(IPP_TAG_SUBSCRIPTION), or unsupported (IPP_TAG_UNSUPPORTED_GROUP).
      +
      +The lower parameter must be less than or equal to the upper parameter.

      ippAddRanges

      Add ranges of values to an IPP message.

      ipp_attribute_t *ippAddRanges (
          ipp_t *ipp,
      -    ipp_tag_t group,
      +    ipp_tag_t group,
          const char *name,
          int num_values,
          const int *lower,
      @@ -2892,12 +3084,21 @@ ssize_t httpWrite2 (

      Return Value

      New attribute

      +

      Discussion

      +

      The ipp parameter refers to an IPP message previously created using the +ippNew or ippNewRequest functions.
      +
      +The group parameter specifies the IPP attribute group tag: none +(IPP_TAG_ZERO, for member attributes), document (IPP_TAG_DOCUMENT), +event notification (IPP_TAG_EVENT_NOTIFICATION), operation +(IPP_TAG_OPERATION), printer (IPP_TAG_PRINTER), subscription +(IPP_TAG_SUBSCRIPTION), or unsupported (IPP_TAG_UNSUPPORTED_GROUP).

      ippAddResolution

      Add a resolution value to an IPP message.

      ipp_attribute_t *ippAddResolution (
          ipp_t *ipp,
      -    ipp_tag_t group,
      +    ipp_tag_t group,
          const char *name,
          ipp_res_t units,
          int xres,
      @@ -2920,12 +3121,21 @@ ssize_t httpWrite2 (

      Return Value

      New attribute

      +

      Discussion

      +

      The ipp parameter refers to an IPP message previously created using the +ippNew or ippNewRequest functions.
      +
      +The group parameter specifies the IPP attribute group tag: none +(IPP_TAG_ZERO, for member attributes), document (IPP_TAG_DOCUMENT), +event notification (IPP_TAG_EVENT_NOTIFICATION), operation +(IPP_TAG_OPERATION), printer (IPP_TAG_PRINTER), subscription +(IPP_TAG_SUBSCRIPTION), or unsupported (IPP_TAG_UNSUPPORTED_GROUP).

      ippAddResolutions

      Add resolution values to an IPP message.

      ipp_attribute_t *ippAddResolutions (
          ipp_t *ipp,
      -    ipp_tag_t group,
      +    ipp_tag_t group,
          const char *name,
          int num_values,
          ipp_res_t units,
      @@ -2951,6 +3161,15 @@ ssize_t httpWrite2 (

      Return Value

      New attribute

      +

      Discussion

      +

      The ipp parameter refers to an IPP message previously created using the +ippNew or ippNewRequest functions.
      +
      +The group parameter specifies the IPP attribute group tag: none +(IPP_TAG_ZERO, for member attributes), document (IPP_TAG_DOCUMENT), +event notification (IPP_TAG_EVENT_NOTIFICATION), operation +(IPP_TAG_OPERATION), printer (IPP_TAG_PRINTER), subscription +(IPP_TAG_SUBSCRIPTION), or unsupported (IPP_TAG_UNSUPPORTED_GROUP).

      ippAddSeparator

      Add a group separator to an IPP message.

      @@ -2964,15 +3183,18 @@ ssize_t httpWrite2 (

      Return Value

      New attribute

      +

      Discussion

      +

      The ipp parameter refers to an IPP message previously created using the +ippNew or ippNewRequest functions.

      ippAddString

      Add a language-encoded string to an IPP message.

      ipp_attribute_t *ippAddString (
          ipp_t *ipp,
      -    ipp_tag_t group,
      -    ipp_tag_t type,
      +    ipp_tag_t group,
      +    ipp_tag_t value_tag,
          const char *name,
      -    const char *charset,
      +    const char *language,
          const char *value
      );

      Parameters

      @@ -2981,27 +3203,46 @@ ssize_t httpWrite2 (
      IPP message
      group
      IPP group
      -
      type
      +
      value_tag
      Type of attribute
      name
      Name of attribute
      -
      charset
      -
      Character set
      +
      language
      +
      Language code
      value
      Value

      Return Value

      New attribute

      +

      Discussion

      +

      The ipp parameter refers to an IPP message previously created using the +ippNew or ippNewRequest functions.
      +
      +The group parameter specifies the IPP attribute group tag: none +(IPP_TAG_ZERO, for member attributes), document (IPP_TAG_DOCUMENT), +event notification (IPP_TAG_EVENT_NOTIFICATION), operation +(IPP_TAG_OPERATION), printer (IPP_TAG_PRINTER), subscription +(IPP_TAG_SUBSCRIPTION), or unsupported (IPP_TAG_UNSUPPORTED_GROUP).
      +
      +Supported string values include charset (IPP_TAG_CHARSET), keyword +(IPP_TAG_KEYWORD), language (IPP_TAG_LANGUAGE), mimeMediaType +(IPP_TAG_MIMETYPE), name (IPP_TAG_NAME), nameWithLanguage +(IPP_TAG_NAMELANG), text (code IPP_TAG_TEXT@), textWithLanguage +(IPP_TAG_TEXTLANG), uri (IPP_TAG_URI), and uriScheme +(IPP_TAG_URISCHEME).
      +
      +The language parameter must be non-NULL for nameWithLanguage and +textWithLanguage string values and must be NULL for all other string values.

      ippAddStrings

      Add language-encoded strings to an IPP message.

      ipp_attribute_t *ippAddStrings (
          ipp_t *ipp,
      -    ipp_tag_t group,
      -    ipp_tag_t type,
      +    ipp_tag_t group,
      +    ipp_tag_t value_tag,
          const char *name,
          int num_values,
      -    const char *charset,
      +    const char *language,
          const char *const *values
      );

      Parameters

      @@ -3010,19 +3251,126 @@ ssize_t httpWrite2 (
      IPP message
      group
      IPP group
      -
      type
      +
      value_tag
      Type of attribute
      name
      Name of attribute
      num_values
      Number of values
      -
      charset
      -
      Character set
      +
      language
      +
      Language code (NULL for default)
      values
      Values

      Return Value

      New attribute

      +

      Discussion

      +

      The ipp parameter refers to an IPP message previously created using the +ippNew or ippNewRequest functions.
      +
      +The group parameter specifies the IPP attribute group tag: none +(IPP_TAG_ZERO, for member attributes), document (IPP_TAG_DOCUMENT), +event notification (IPP_TAG_EVENT_NOTIFICATION), operation +(IPP_TAG_OPERATION), printer (IPP_TAG_PRINTER), subscription +(IPP_TAG_SUBSCRIPTION), or unsupported (IPP_TAG_UNSUPPORTED_GROUP).
      +
      +Supported string values include charset (IPP_TAG_CHARSET), keyword +(IPP_TAG_KEYWORD), language (IPP_TAG_LANGUAGE), mimeMediaType +(IPP_TAG_MIMETYPE), name (IPP_TAG_NAME), nameWithLanguage +(IPP_TAG_NAMELANG), text (code IPP_TAG_TEXT@), textWithLanguage +(IPP_TAG_TEXTLANG), uri (IPP_TAG_URI), and uriScheme +(IPP_TAG_URISCHEME).
      +
      +The language parameter must be non-NULL for nameWithLanguage and +textWithLanguage string values and must be NULL for all other string values.

      +

       CUPS 1.6 ippAttributeString

      +

      Convert the attribute's value to a string.

      +

      +size_t ippAttributeString (
      +    ipp_attribute_t *attr,
      +    char *buffer,
      +    size_t bufsize
      +);

      +

      Parameters

      +
      +
      attr
      +
      Attribute
      +
      buffer
      +
      String buffer or NULL
      +
      bufsize
      +
      Size of string buffer
      +
      +

      Return Value

      +

      Number of bytes less nul

      +

      Discussion

      +

      Returns the number of bytes that would be written, not including the +trailing nul. The buffer pointer can be NULL to get the required length, +just like (v)snprintf. + +

      +

       CUPS 1.6 ippCopyAttribute

      +

      Copy an attribute.

      +

      +ipp_attribute_t *ippCopyAttribute (
      +    ipp_t *dst,
      +    ipp_attribute_t *srcattr,
      +    int quickcopy
      +);

      +

      Parameters

      +
      +
      dst
      +
      Destination IPP message
      +
      srcattr
      +
      Attribute to copy
      +
      quickcopy
      +
      1 for a referenced copy, 0 for normal
      +
      +

      Return Value

      +

      New attribute

      +

      Discussion

      +

      The specified attribute, attr, is copied to the destination IPP message. +When quickcopy is non-zero, a "shallow" reference copy of the attribute is +created - this should only be done as long as the original source IPP message will +not be freed for the life of the destination. + +

      +

       CUPS 1.6 ippCopyAttributes

      +

      Copy attributes from one IPP message to another.

      +

      +int ippCopyAttributes (
      +    ipp_t *dst,
      +    ipp_t *src,
      +    int quickcopy,
      +    ipp_copycb_t cb,
      +    void *context
      +);

      +

      Parameters

      +
      +
      dst
      +
      Destination IPP message
      +
      src
      +
      Source IPP message
      +
      quickcopy
      +
      1 for a referenced copy, 0 for normal
      +
      cb
      +
      Copy callback or NULL for none
      +
      context
      +
      Context pointer
      +
      +

      Return Value

      +

      1 on success, 0 on error

      +

      Discussion

      +

      Zero or more attributes are copied from the source IPP message, @code@ src, to the +destination IPP message, dst. When quickcopy is non-zero, a "shallow" +reference copy of the attribute is created - this should only be done as long as the +original source IPP message will not be freed for the life of the destination.
      +
      +The cb and context parameters provide a generic way to "filter" the +attributes that are copied - the function must return 1 to copy the attribute or +0 to skip it. The function may also choose to do a partial copy of the source attribute +itself. + +

      ippDateToTime

      Convert from RFC 1903 Date/Time format to UNIX time in seconds.

      @@ -3062,6 +3410,67 @@ void ippDeleteAttribute (
      attr
      Attribute to delete
      +

       CUPS 1.6 ippDeleteValues

      +

      Delete values in an attribute.

      +

      +int ippDeleteValues (
      +    ipp_t *ipp,
      +    ipp_attribute_t *attr,
      +    int element,
      +    int count
      +);

      +

      Parameters

      +
      +
      ipp
      +
      IPP message
      +
      attr
      +
      Attribute
      +
      element
      +
      Index of first value to delete (0-based)
      +
      count
      +
      Number of values to delete
      +
      +

      Return Value

      +

      1 on success, 0 on failure

      +

      Discussion

      +

      The element parameter specifies the first value to delete, starting at 0. It +must be less than the number of values returned by ippGetCount.
      +
      +Deleting all values in an attribute deletes the attribute. + +

      +

      ippEnumString

      +

      Return a string corresponding to the enum value.

      +

      +const char *ippEnumString (
      +    const char *attrname,
      +    int enumvalue
      +);

      +

      Parameters

      +
      +
      attrname
      +
      Attribute name
      +
      enumvalue
      +
      Enum value
      +
      +

      Return Value

      +

      Enum string

      +

      ippEnumValue

      +

      Return the value associated with a given enum string.

      +

      +int ippEnumValue (
      +    const char *attrname,
      +    const char *enumstring
      +);

      +

      Parameters

      +
      +
      attrname
      +
      Attribute name
      +
      enumstring
      +
      Enum string
      +
      +

      Return Value

      +

      Enum value or -1 if unknown

      ippErrorString

      Return a name for the given status code.

      @@ -3094,7 +3503,7 @@ ipp_status_t ippErrorValue (
      ipp_attribute_t *ippFindAttribute (
          ipp_t *ipp,
          const char *name,
      -    ipp_tag_t type
      +    ipp_tag_t type
      );

      Parameters

      @@ -3113,7 +3522,7 @@ ipp_status_t ippErrorValue (
      ipp_attribute_t *ippFindNextAttribute (
          ipp_t *ipp,
          const char *name,
      -    ipp_tag_t type
      +    ipp_tag_t type
      );

      Parameters

      @@ -3126,10 +3535,10 @@ ipp_status_t ippErrorValue (

      Return Value

      Matching attribute

      -

      ippLength

      -

      Compute the length of an IPP message.

      +

       CUPS 1.6 ippFirstAttribute

      +

      Return the first attribute in the message.

      -size_t ippLength (
      +ipp_attribute_t *ippFirstAttribute (
          ipp_t *ipp
      );

      Parameters

      @@ -3138,143 +3547,777 @@ size_t ippLength (
      IPP message

      Return Value

      -

      Size of IPP message

      -

      ippNew

      -

      Allocate a new IPP message.

      -

      -ipp_t *ippNew (void);

      -

      Return Value

      -

      New IPP message

      -

       CUPS 1.2/Mac OS X 10.5 ippNewRequest

      -

      Allocate a new IPP request message.

      +

      First attribute or NULL if none

      +

       CUPS 1.6 ippGetBoolean

      +

      Get a boolean value for an attribute.

      -ipp_t *ippNewRequest (
      -    ipp_op_t op
      +int ippGetBoolean (
      +    ipp_attribute_t *attr,
      +    int element
      );

      Parameters

      -
      op
      -
      Operation code
      +
      attr
      +
      IPP attribute
      +
      element
      +
      Value number (0-based)

      Return Value

      -

      IPP request message

      +

      Boolean value or -1 on error

      Discussion

      -

      The new request message is initialized with the attributes-charset and -attributes-natural-language attributes added. The -attributes-natural-language value is derived from the current locale. +

      The element parameter specifies which value to get from 0 to +ippGetCount(attr) - 1.

      -

       CUPS 1.2/Mac OS X 10.5 ippOpString

      -

      Return a name for the given operation id.

      +

       CUPS 1.6 ippGetCollection

      +

      Get a collection value for an attribute.

      -const char *ippOpString (
      -    ipp_op_t op
      +ipp_t *ippGetCollection (
      +    ipp_attribute_t *attr,
      +    int element
      );

      Parameters

      -
      op
      -
      Operation ID
      +
      attr
      +
      IPP attribute
      +
      element
      +
      Value number (0-based)

      Return Value

      -

      Name

      -

       CUPS 1.2/Mac OS X 10.5 ippOpValue

      -

      Return an operation id for the given name.

      +

      Collection value or NULL on error

      +

      Discussion

      +

      The element parameter specifies which value to get from 0 to +ippGetCount(attr) - 1. + +

      +

       CUPS 1.6 ippGetCount

      +

      Get the number of values in an attribute.

      -ipp_op_t ippOpValue (
      -    const char *name
      +int ippGetCount (
      +    ipp_attribute_t *attr
      );

      Parameters

      -
      name
      -
      Textual name
      +
      attr
      +
      IPP attribute

      Return Value

      -

      Operation ID

      -

      ippPort

      -

      Return the default IPP port number.

      +

      Number of values or -1 on error

      +

       CUPS 1.6 ippGetGroupTag

      +

      Get the group associated with an attribute.

      -int ippPort (void);

      +ipp_tag_t ippGetGroupTag (
      +    ipp_attribute_t *attr
      +);

      +

      Parameters

      +
      +
      attr
      +
      IPP attribute
      +

      Return Value

      -

      Port number

      -

      ippRead

      -

      Read data for an IPP message from a HTTP connection.

      +

      Group tag or IPP_TAG_ZERO on error

      +

       CUPS 1.6 ippGetInteger

      +

      Get the integer/enum value for an attribute.

      -ipp_state_t ippRead (
      -    http_t *http,
      -    ipp_t *ipp
      +int ippGetInteger (
      +    ipp_attribute_t *attr,
      +    int element
      );

      Parameters

      -
      http
      -
      HTTP connection
      -
      ipp
      -
      IPP data
      +
      attr
      +
      IPP attribute
      +
      element
      +
      Value number (0-based)

      Return Value

      -

      Current state

      -

       CUPS 1.1.19/Mac OS X 10.3 ippReadFile

      -

      Read data for an IPP message from a file.

      +

      Value or -1 on error

      +

      Discussion

      +

      The element parameter specifies which value to get from 0 to +ippGetCount(attr) - 1. + +

      +

       CUPS 1.6 ippGetName

      +

      Get the attribute name.

      -ipp_state_t ippReadFile (
      -    int fd,
      -    ipp_t *ipp
      +const char *ippGetName (
      +    ipp_attribute_t *attr
      );

      Parameters

      -
      fd
      -
      HTTP data
      -
      ipp
      -
      IPP data
      +
      attr
      +
      IPP attribute

      Return Value

      -

      Current state

      -

       CUPS 1.2/Mac OS X 10.5 ippReadIO

      -

      Read data for an IPP message.

      +

      Attribute name or NULL for separators

      +

       CUPS 1.6 ippGetOperation

      +

      Get the operation ID in an IPP message.

      -ipp_state_t ippReadIO (
      -    void *src,
      -    ipp_iocb_t cb,
      -    int blocking,
      -    ipp_t *parent,
      +ipp_op_t ippGetOperation (
          ipp_t *ipp
      );

      Parameters

      -
      src
      -
      Data source
      -
      cb
      -
      Read callback function
      -
      blocking
      -
      Use blocking IO?
      -
      parent
      -
      Parent request, if any
      ipp
      -
      IPP data
      +
      IPP request message

      Return Value

      -

      Current state

      -

      ippSetPort

      -

      Set the default port number.

      +

      Operation ID or -1 on error

      +

       CUPS 1.6 ippGetRequestId

      +

      Get the request ID from an IPP message.

      -void ippSetPort (
      -    int p
      +int ippGetRequestId (
      +    ipp_t *ipp
      );

      Parameters

      -
      p
      -
      Port number to use
      +
      ipp
      +
      IPP message
      -

       CUPS 1.4/Mac OS X 10.6 ippTagString

      -

      Return the tag name corresponding to a tag value.

      -

      -const char *ippTagString (
      -    ipp_tag_t tag
      +

      Return Value

      +

      Request ID or -1 on error

      +

       CUPS 1.6 ippGetResolution

      +

      Get a resolution value for an attribute.

      +

      +int ippGetResolution (
      +    ipp_attribute_t *attr,
      +    int element,
      +    int *yres,
      +    ipp_res_t *units
      );

      Parameters

      -
      tag
      -
      Tag value
      -
      +
      attr
      +
      IPP attribute
      +
      element
      +
      Value number (0-based)
      +
      yres
      +
      Vertical/feed resolution
      +
      units
      +
      Units for resolution
      + +

      Return Value

      +

      Horizontal/cross feed resolution or -1

      +

      Discussion

      +

      The element parameter specifies which value to get from 0 to +ippGetCount(attr) - 1. + +

      +

       CUPS 1.6 ippGetStatusCode

      +

      Get the status code from an IPP response or event message.

      +

      +ipp_status_t ippGetStatusCode (
      +    ipp_t *ipp
      +);

      +

      Parameters

      +
      +
      ipp
      +
      IPP response or event message
      +
      +

      Return Value

      +

      Status code in IPP message

      +

      ippGetString

      +

      Return the value...

      +

      +const char *ippGetString (
      +    ipp_attribute_t *attr,
      +    int element,
      +    const char **language
      +);

      +

      Parameters

      +
      +
      attr
      +
      IPP attribute
      +
      element
      +
      Value number (0-based)
      +
      language
      +
      Language code (NULL for don't care)
      +
      +

      Return Value

      +

      Get the string and optionally the language code for an attribute.

      +

      The element parameter specifies which value to get from 0 to +ippGetCount(attr) - 1. + +

      +

       CUPS 1.6 ippGetValueTag

      +

      Get the value tag for an attribute.

      +

      +ipp_tag_t ippGetValueTag (
      +    ipp_attribute_t *attr
      +);

      +

      Parameters

      +
      +
      attr
      +
      IPP attribute
      +
      +

      Return Value

      +

      Value tag or IPP_TAG_ZERO on error

      +

       CUPS 1.6 ippGetVersion

      +

      Get the major and minor version number from an IPP message.

      +

      +int ippGetVersion (
      +    ipp_t *ipp,
      +    int *minor
      +);

      +

      Parameters

      +
      +
      ipp
      +
      IPP message
      +
      minor
      +
      Minor version number or NULL
      +
      +

      Return Value

      +

      Major version number or -1 on error

      +

      ippLength

      +

      Compute the length of an IPP message.

      +

      +size_t ippLength (
      +    ipp_t *ipp
      +);

      +

      Parameters

      +
      +
      ipp
      +
      IPP message
      +
      +

      Return Value

      +

      Size of IPP message

      +

      ippNew

      +

      Allocate a new IPP message.

      +

      +ipp_t *ippNew (void);

      +

      Return Value

      +

      New IPP message

      +

       CUPS 1.2/Mac OS X 10.5 ippNewRequest

      +

      Allocate a new IPP request message.

      +

      +ipp_t *ippNewRequest (
      +    ipp_op_t op
      +);

      +

      Parameters

      +
      +
      op
      +
      Operation code
      +
      +

      Return Value

      +

      IPP request message

      +

      Discussion

      +

      The new request message is initialized with the attributes-charset and +attributes-natural-language attributes added. The +attributes-natural-language value is derived from the current locale. + +

      +

       CUPS 1.6 ippNextAttribute

      +

      Return the next attribute in the message.

      +

      +ipp_attribute_t *ippNextAttribute (
      +    ipp_t *ipp
      +);

      +

      Parameters

      +
      +
      ipp
      +
      IPP message
      +
      +

      Return Value

      +

      Next attribute or NULL if none

      +

       CUPS 1.2/Mac OS X 10.5 ippOpString

      +

      Return a name for the given operation id.

      +

      +const char *ippOpString (
      +    ipp_op_t op
      +);

      +

      Parameters

      +
      +
      op
      +
      Operation ID
      +
      +

      Return Value

      +

      Name

      +

       CUPS 1.2/Mac OS X 10.5 ippOpValue

      +

      Return an operation id for the given name.

      +

      +ipp_op_t ippOpValue (
      +    const char *name
      +);

      +

      Parameters

      +
      +
      name
      +
      Textual name
      +
      +

      Return Value

      +

      Operation ID

      +

      ippPort

      +

      Return the default IPP port number.

      +

      +int ippPort (void);

      +

      Return Value

      +

      Port number

      +

      ippRead

      +

      Read data for an IPP message from a HTTP connection.

      +

      +ipp_state_t ippRead (
      +    http_t *http,
      +    ipp_t *ipp
      +);

      +

      Parameters

      +
      +
      http
      +
      HTTP connection
      +
      ipp
      +
      IPP data
      +
      +

      Return Value

      +

      Current state

      +

       CUPS 1.1.19/Mac OS X 10.3 ippReadFile

      +

      Read data for an IPP message from a file.

      +

      +ipp_state_t ippReadFile (
      +    int fd,
      +    ipp_t *ipp
      +);

      +

      Parameters

      +
      +
      fd
      +
      HTTP data
      +
      ipp
      +
      IPP data
      +
      +

      Return Value

      +

      Current state

      +

       CUPS 1.2/Mac OS X 10.5 ippReadIO

      +

      Read data for an IPP message.

      +

      +ipp_state_t ippReadIO (
      +    void *src,
      +    ipp_iocb_t cb,
      +    int blocking,
      +    ipp_t *parent,
      +    ipp_t *ipp
      +);

      +

      Parameters

      +
      +
      src
      +
      Data source
      +
      cb
      +
      Read callback function
      +
      blocking
      +
      Use blocking IO?
      +
      parent
      +
      Parent request, if any
      +
      ipp
      +
      IPP data
      +
      +

      Return Value

      +

      Current state

      +

       CUPS 1.6 ippSetBoolean

      +

      Set a boolean value in an attribute.

      +

      +int ippSetBoolean (
      +    ipp_t *ipp,
      +    ipp_attribute_t **attr,
      +    int element,
      +    int boolvalue
      +);

      +

      Parameters

      +
      +
      ipp
      +
      IPP message
      +
      attr
      +
      IPP attribute
      +
      element
      +
      Value number (0-based)
      +
      boolvalue
      +
      Boolean value
      +
      +

      Return Value

      +

      1 on success, 0 on failure

      +

      Discussion

      +

      The ipp parameter refers to the IPP message containing the attribute that was +previously created using the ippNew or ippNewRequest functions.
      +
      +The attr parameter may be modified as a result of setting the value.
      +
      +The element parameter specifies which value to set from 0 to +ippGetCount(attr). + +

      +

       CUPS 1.6 ippSetCollection

      +

      Set a collection value in an attribute.

      +

      +int ippSetCollection (
      +    ipp_t *ipp,
      +    ipp_attribute_t **attr,
      +    int element,
      +    ipp_t *colvalue
      +);

      +

      Parameters

      +
      +
      ipp
      +
      IPP message
      +
      attr
      +
      IPP attribute
      +
      element
      +
      Value number (0-based)
      +
      colvalue
      +
      Collection value
      +
      +

      Return Value

      +

      1 on success, 0 on failure

      +

      Discussion

      +

      The ipp parameter refers to the IPP message containing the attribute that was +previously created using the ippNew or ippNewRequest functions.
      +
      +The attr parameter may be modified as a result of setting the value.
      +
      +The element parameter specifies which value to set from 0 to +ippGetCount(attr). + +

      +

       CUPS 1.6 ippSetGroupTag

      +

      Set the group tag of an attribute.

      +

      +int ippSetGroupTag (
      +    ipp_t *ipp,
      +    ipp_attribute_t **attr,
      +    ipp_tag_t group_tag
      +);

      +

      Parameters

      +
      +
      ipp
      +
      IPP message
      +
      attr
      +
      Attribute
      +
      group_tag
      +
      Group tag
      +
      +

      Return Value

      +

      1 on success, 0 on failure

      +

      Discussion

      +

      The ipp parameter refers to the IPP message containing the attribute that was +previously created using the ippNew or ippNewRequest functions.
      +
      +The attr parameter may be modified as a result of setting the value.
      +
      +The group parameter specifies the IPP attribute group tag: none +(IPP_TAG_ZERO, for member attributes), document (IPP_TAG_DOCUMENT), +event notification (IPP_TAG_EVENT_NOTIFICATION), operation +(IPP_TAG_OPERATION), printer (IPP_TAG_PRINTER), subscription +(IPP_TAG_SUBSCRIPTION), or unsupported (IPP_TAG_UNSUPPORTED_GROUP). + +

      +

       CUPS 1.6 ippSetInteger

      +

      Set an integer or enum value in an attribute.

      +

      +int ippSetInteger (
      +    ipp_t *ipp,
      +    ipp_attribute_t **attr,
      +    int element,
      +    int intvalue
      +);

      +

      Parameters

      +
      +
      ipp
      +
      IPP message
      +
      attr
      +
      IPP attribute
      +
      element
      +
      Value number (0-based)
      +
      intvalue
      +
      Integer/enum value
      +
      +

      Return Value

      +

      1 on success, 0 on failure

      +

      Discussion

      +

      The ipp parameter refers to the IPP message containing the attribute that was +previously created using the ippNew or ippNewRequest functions.
      +
      +The attr parameter may be modified as a result of setting the value.
      +
      +The element parameter specifies which value to set from 0 to +ippGetCount(attr). + +

      +

       CUPS 1.6 ippSetName

      +

      Set the name of an attribute.

      +

      +int ippSetName (
      +    ipp_t *ipp,
      +    ipp_attribute_t **attr,
      +    const char *name
      +);

      +

      Parameters

      +
      +
      ipp
      +
      IPP message
      +
      attr
      +
      IPP attribute
      +
      name
      +
      Attribute name
      +
      +

      Return Value

      +

      1 on success, 0 on failure

      +

      Discussion

      +

      The ipp parameter refers to the IPP message containing the attribute that was +previously created using the ippNew or ippNewRequest functions.
      +
      +The attr parameter may be modified as a result of setting the value. + +

      +

       CUPS 1.6 ippSetOperation

      +

      Set the operation ID in an IPP request message.

      +

      +int ippSetOperation (
      +    ipp_t *ipp,
      +    ipp_op_t op
      +);

      +

      Parameters

      +
      +
      ipp
      +
      IPP request message
      +
      op
      +
      Operation ID
      +
      +

      Return Value

      +

      1 on success, 0 on failure

      +

      Discussion

      +

      The ipp parameter refers to an IPP message previously created using the +ippNew or ippNewRequest functions. + +

      +

      ippSetPort

      +

      Set the default port number.

      +

      +void ippSetPort (
      +    int p
      +);

      +

      Parameters

      +
      +
      p
      +
      Port number to use
      +
      +

       CUPS 1.6 ippSetRange

      +

      Set a rangeOfInteger value in an attribute.

      +

      +int ippSetRange (
      +    ipp_t *ipp,
      +    ipp_attribute_t **attr,
      +    int element,
      +    int lowervalue,
      +    int uppervalue
      +);

      +

      Parameters

      +
      +
      ipp
      +
      IPP message
      +
      attr
      +
      IPP attribute
      +
      element
      +
      Value number (0-based)
      +
      lowervalue
      +
      Lower bound for range
      +
      uppervalue
      +
      Upper bound for range
      +
      +

      Return Value

      +

      1 on success, 0 on failure

      +

      Discussion

      +

      The ipp parameter refers to the IPP message containing the attribute that was +previously created using the ippNew or ippNewRequest functions.
      +
      +The attr parameter may be modified as a result of setting the value.
      +
      +The element parameter specifies which value to set from 0 to +ippGetCount(attr). + +

      +

       CUPS 1.6 ippSetRequestId

      +

      Set the request ID in an IPP message.

      +

      +int ippSetRequestId (
      +    ipp_t *ipp,
      +    int request_id
      +);

      +

      Parameters

      +
      +
      ipp
      +
      IPP message
      +
      request_id
      +
      Request ID
      +
      +

      Return Value

      +

      1 on success, 0 on failure

      +

      Discussion

      +

      The ipp parameter refers to an IPP message previously created using the +ippNew or ippNewRequest functions.
      +
      +The request_id parameter must be greater than 0. + +

      +

       CUPS 1.6 ippSetResolution

      +

      Set a resolution value in an attribute.

      +

      +int ippSetResolution (
      +    ipp_t *ipp,
      +    ipp_attribute_t **attr,
      +    int element,
      +    ipp_res_t unitsvalue,
      +    int xresvalue,
      +    int yresvalue
      +);

      +

      Parameters

      +
      +
      ipp
      +
      IPP message
      +
      attr
      +
      IPP attribute
      +
      element
      +
      Value number (0-based)
      +
      unitsvalue
      +
      Resolution units
      +
      xresvalue
      +
      Horizontal/cross feed resolution
      +
      yresvalue
      +
      Vertical/feed resolution
      +
      +

      Return Value

      +

      1 on success, 0 on failure

      +

      Discussion

      +

      The ipp parameter refers to the IPP message containing the attribute that was +previously created using the ippNew or ippNewRequest functions.
      +
      +The attr parameter may be modified as a result of setting the value.
      +
      +The element parameter specifies which value to set from 0 to +ippGetCount(attr). + +

      +

       CUPS 1.6 ippSetStatusCode

      +

      Set the status code in an IPP response or event message.

      +

      +int ippSetStatusCode (
      +    ipp_t *ipp,
      +    ipp_status_t status
      +);

      +

      Parameters

      +
      +
      ipp
      +
      IPP response or event message
      +
      status
      +
      Status code
      +
      +

      Return Value

      +

      1 on success, 0 on failure

      +

      Discussion

      +

      The ipp parameter refers to an IPP message previously created using the +ippNew or ippNewRequest functions. + +

      +

       CUPS 1.6 ippSetString

      +

      Set a string value in an attribute.

      +

      +int ippSetString (
      +    ipp_t *ipp,
      +    ipp_attribute_t **attr,
      +    int element,
      +    const char *strvalue
      +);

      +

      Parameters

      +
      +
      ipp
      +
      IPP message
      +
      attr
      +
      IPP attribute
      +
      element
      +
      Value number (0-based)
      +
      strvalue
      +
      String value
      +
      +

      Return Value

      +

      1 on success, 0 on failure

      +

      Discussion

      +

      The ipp parameter refers to the IPP message containing the attribute that was +previously created using the ippNew or ippNewRequest functions.
      +
      +The attr parameter may be modified as a result of setting the value.
      +
      +The element parameter specifies which value to set from 0 to +ippGetCount(attr). + +

      +

       CUPS 1.6 ippSetValueTag

      +

      Set the value tag of an attribute.

      +

      +int ippSetValueTag (
      +    ipp_t *ipp,
      +    ipp_attribute_t **attr,
      +    ipp_tag_t value_tag
      +);

      +

      Parameters

      +
      +
      ipp
      +
      IPP message
      +
      attr
      +
      IPP attribute
      +
      value_tag
      +
      Value tag
      +
      +

      Return Value

      +

      1 on success, 0 on failure

      +

      Discussion

      +

      The ipp parameter refers to the IPP message containing the attribute that was +previously created using the ippNew or ippNewRequest functions.
      +
      +The attr parameter may be modified as a result of setting the value.
      +
      +Integer (IPP_TAG_INTEGER) values can be promoted to rangeOfInteger +(IPP_TAG_RANGE) values, the various string tags can be promoted to name +(IPP_TAG_NAME) or nameWithLanguage (IPP_TAG_NAMELANG) values, text +(IPP_TAG_TEXT) values can be promoted to textWithLanguage +(IPP_TAG_TEXTLANG) values, and all values can be demoted to the various +out-of-band value tags such as no-value (IPP_TAG_NOVALUE). All other changes +will be rejected.
      +
      +Promoting a string attribute to nameWithLanguage or textWithLanguage adds the language +code in the "attributes-natural-language" attribute or, if not present, the language +code for the current locale. + +

      +

       CUPS 1.6 ippSetVersion

      +

      Set the version number in an IPP message.

      +

      +int ippSetVersion (
      +    ipp_t *ipp,
      +    int major,
      +    int minor
      +);

      +

      Parameters

      +
      +
      ipp
      +
      IPP message
      +
      major
      +
      Major version number (major.minor)
      +
      minor
      +
      Minor version number (major.minor)
      +
      +

      Return Value

      +

      1 on success, 0 on failure

      +

      Discussion

      +

      The ipp parameter refers to an IPP message previously created using the +ippNew or ippNewRequest functions.
      +
      +The valid version numbers are currently 1.0, 1.1, 2.0, 2.1, and 2.2. + +

      +

       CUPS 1.4/Mac OS X 10.6 ippTagString

      +

      Return the tag name corresponding to a tag value.

      +

      +const char *ippTagString (
      +    ipp_tag_t tag
      +);

      +

      Parameters

      +
      +
      tag
      +
      Tag value
      +

      Return Value

      Tag name

      Discussion

      @@ -3284,7 +4327,7 @@ const char *ippTagString (

       CUPS 1.4/Mac OS X 10.6 ippTagValue

      Return the tag value corresponding to a tag name.

      -ipp_tag_t ippTagValue (
      +ipp_tag_t ippTagValue (
          const char *name
      );

      Parameters

      @@ -3457,9 +4500,19 @@ typedef enum http_uri_status_e http_uri_status_ typedef enum http_version_e http_version_t;

      ipp_attribute_t

      -

      Attribute

      +

      IPP attribute

      -typedef struct ipp_attribute_s ipp_attribute_t; +typedef struct _ipp_attribute_s ipp_attribute_t; +

      +

      ipp_copycb_t

      +

      Prototypes...

      +

      +typedef int (*ipp_copycb_t)(void *context, ipp_t *dst, ipp_attribute_t *attr); +

      +

      ipp_dstate_t

      +

      Document states

      +

      +typedef enum ipp_dstate_e ipp_dstate_t;

      ipp_finish_t

      Finishings

      @@ -3469,17 +4522,12 @@ typedef enum ipp_finish_e ipp_finish_t;

       CUPS 1.2/Mac OS X 10.5 ipp_iocb_t

      IPP IO Callback Function

      -typedef ssize_t (*ipp_iocb_t)(void *, ipp_uchar_t *, size_t); +typedef ssize_t (*ipp_iocb_t)(void *context, ipp_uchar_t *buffer, size_t bytes);

      -

      ipp_jstate_t

      -

      Job states

      +

      ipp_jcollate_t

      +

      Job collation types

      -typedef enum ipp_jstate_e ipp_jstate_t; -

      -

      ipp_op_t

      -

      IPP operations

      -

      -typedef enum ipp_op_e ipp_op_t; +typedef enum ipp_jcollate_e ipp_jcollate_t;

      ipp_orient_t

      Orientation values

      @@ -3496,11 +4544,6 @@ typedef enum ipp_pstate_e ipp_pstate_t;

      typedef enum ipp_quality_e ipp_quality_t;

      -

      ipp_request_t

      -

      Request Header

      -

      -typedef union ipp_request_u ipp_request_t; -

      ipp_res_t

      Resolution units

      @@ -3512,24 +4555,14 @@ typedef enum ipp_res_e ipp_res_t; typedef enum ipp_state_e ipp_state_t;

      ipp_t

      -

      Attribute Value

      +

      IPP request/response data

      -typedef struct ipp_s ipp_t; +typedef struct _ipp_s ipp_t;

      ipp_uchar_t

      -

      IPP status codes

      -

      -typedef typedef unsigned char ipp_uchar_t; -

      -

      ipp_tag_t

      -

      Format tags for attributes

      -

      -typedef enum ipp_tag_e ipp_tag_t; -

      -

      ipp_value_t

      -

      Attribute Value

      +

      Unsigned 8-bit integer/character

      -typedef union ipp_value_u ipp_value_t; +typedef unsigned char ipp_uchar_t;

      Structures

      gss_auth_identity

      @@ -3580,86 +4613,6 @@ with a hostname.

      datalen
      Credential length
      -

      ipp_attribute_s

      -

      Attribute

      -

      struct ipp_attribute_s {
      -    char *name;
      -    struct ipp_attribute_s *next;
      -    int num_values;
      -    ipp_tag_t group_tag, value_tag;
      -    ipp_value_t values[1];
      -};

      -

      Members

      -
      -
      name
      -
      Name of attribute
      -
      next
      -
      Next attribute in list
      -
      num_values
      -
      Number of values
      -
      value_tag
      -
      What type of value is it?
      -
      values[1]
      -
      Values
      -
      -

      ipp_s

      -

      IPP Request/Response/Notification

      -

      struct ipp_s {
      -    ipp_attribute_t *attrs;
      -    ipp_attribute_t *current;
      -    ipp_tag_t curtag;
      -    ipp_attribute_t *last;
      -    ipp_attribute_t *prev;
      -    ipp_request_t request;
      -    ipp_state_t state;
      -    int use;
      -};

      -

      Members

      -
      -
      attrs
      -
      Attributes
      -
      current
      -
      Current attribute (for read/write)
      -
      curtag
      -
      Current attribute group tag
      -
      last
      -
      Last attribute in list
      -
      prev  CUPS 1.2/Mac OS X 10.5 
      -
      Previous attribute (for read)
      -
      request
      -
      Request header
      -
      state
      -
      State of request
      -
      use  CUPS 1.4.4/Mac OS X 10.6.? 
      -
      Use count
      -
      -

      Unions

      -

      ipp_request_u

      -

      Request Header

      -

      union ipp_request_u {
      -};

      -

      Members

      -
      -
      -

      ipp_value_u

      -

      Attribute Value

      -

      union ipp_value_u {
      -    char boolean;
      -    ipp_t *collection;
      -    ipp_uchar_t date[11];
      -    int integer;
      -};

      -

      Members

      -
      -
      boolean
      -
      Boolean value
      -
      collection  CUPS 1.1.19/Mac OS X 10.3 
      -
      Collection value
      -
      date[11]
      -
      Date/time value
      -
      integer
      -
      Integer/enumerated value
      -

      Constants

      http_auth_e

      HTTP authentication types

      @@ -3960,6 +4913,16 @@ are server-oriented...

      HTTP_1_1
      HTTP/1.1
      +

      ipp_dstate_e

      +

      Document states

      +

      Constants

      +
      +
      IPP_DOCUMENT_ABORTED
      +
      IPP_DOCUMENT_CANCELED
      +
      IPP_DOCUMENT_COMPLETED
      +
      IPP_DOCUMENT_PENDING
      +
      IPP_DOCUMENT_PROCESSING
      +

      ipp_finish_e

      Finishings

      Constants

      @@ -4020,6 +4983,22 @@ are server-oriented...

      Staple top right corner
      IPP_FINISHINGS_TRIM
      Trim (any type)
      +
      IPP_FINISHINGS_TRIM_AFTER_COPIES
      +
      Trim output after each copy
      +
      IPP_FINISHINGS_TRIM_AFTER_DOCUMENTS
      +
      Trim output after each document
      +
      IPP_FINISHINGS_TRIM_AFTER_JOB
      +
      Trim output after job
      +
      IPP_FINISHINGS_TRIM_AFTER_PAGES
      +
      Trim output after each page
      + +

      ipp_jcollate_e

      +

      Job collation types

      +

      Constants

      +
      +
      IPP_JOB_COLLATED_DOCUMENTS
      +
      IPP_JOB_UNCOLLATED_DOCUMENTS
      +
      IPP_JOB_UNCOLLATED_SHEETS

      ipp_jstate_e

      Job states

      @@ -4112,6 +5091,8 @@ are server-oriented...

      Get subscription attributes
      IPP_HOLD_JOB
      Hold a job for printing
      +
      IPP_IDENTIFY_PRINTER
      +
      Identify-Printer (proposed IPP JPS3)
      IPP_PAUSE_PRINTER
      Stop a printer
      IPP_PRINT_JOB
      @@ -4224,14 +5205,20 @@ are server-oriented...

      client-error-document-format-not-supported
      IPP_DOCUMENT_FORMAT_ERROR
      client-error-document-format-error
      +
      IPP_DOCUMENT_PASSWORD_ERROR
      +
      client-error-document-password-error
      +
      IPP_DOCUMENT_PERMISSION_ERROR
      +
      client-error-document-permission-error
      +
      IPP_DOCUMENT_SECURITY_ERROR
      +
      client-error-document-security-error
      +
      IPP_DOCUMENT_UNPRINTABLE_ERROR
      +
      client-error-document-unprintable-error
      IPP_ERROR_JOB_CANCELED
      server-error-job-canceled
      IPP_FORBIDDEN
      client-error-forbidden
      IPP_GONE
      client-error-gone
      -
      IPP_IGNORED_ALL_NOTIFICATIONS
      -
      client-error-ignored-all-notifications
      IPP_IGNORED_ALL_SUBSCRIPTIONS
      client-error-ignored-all-subscriptions
      IPP_INTERNAL_ERROR
      @@ -4250,14 +5237,10 @@ are server-oriented...

      client-error-not-possible
      IPP_OK
      successful-ok
      -
      IPP_OK_BUT_CANCEL_SUBSCRIPTION
      -
      successful-ok-but-cancel-subscription
      IPP_OK_CONFLICT
      successful-ok-conflicting-attributes
      IPP_OK_EVENTS_COMPLETE
      successful-ok-events-complete
      -
      IPP_OK_IGNORED_NOTIFICATIONS
      -
      successful-ok-ignored-notifications
      IPP_OK_IGNORED_SUBSCRIPTIONS
      successful-ok-ignored-subscriptions
      IPP_OK_SUBST
      @@ -4272,8 +5255,6 @@ are server-oriented...

      server-error-busy
      IPP_PRINTER_IS_DEACTIVATED
      server-error-printer-is-deactivated
      -
      IPP_PRINT_SUPPORT_FILE_NOT_FOUND
      -
      client-error-print-support-file-not-found
      IPP_REQUEST_ENTITY
      client-error-request-entity-too-large
      IPP_REQUEST_VALUE
      @@ -4305,14 +5286,14 @@ are server-oriented...

      Boolean value
      IPP_TAG_CHARSET
      Character set value
      -
      IPP_TAG_COPY
      -
      Bitflag for copied attribute values
      IPP_TAG_DATE
      Date/time value
      IPP_TAG_DEFAULT
      Default value
      IPP_TAG_DELETEATTR
      Delete-attribute value
      +
      IPP_TAG_DOCUMENT
      +
      Document group
      IPP_TAG_END
      End-of-attributes
      IPP_TAG_END_COLLECTION
      @@ -4321,6 +5302,8 @@ are server-oriented...

      Enumeration value
      IPP_TAG_EVENT_NOTIFICATION
      Event group
      +
      IPP_TAG_EXTENSION
      +
      Extension point for 32-bit tags
      IPP_TAG_INTEGER
      Integer value
      IPP_TAG_JOB
      @@ -4329,8 +5312,6 @@ are server-oriented...

      Keyword value
      IPP_TAG_LANGUAGE
      Language value
      -
      IPP_TAG_MASK
      -
      Mask for copied attribute values
      IPP_TAG_MEMBERNAME
      Collection member name value
      IPP_TAG_MIMETYPE
      diff --git a/doc/help/api-ppd.html b/doc/help/api-ppd.html index c7b7a6119..574640692 100644 --- a/doc/help/api-ppd.html +++ b/doc/help/api-ppd.html @@ -2,7 +2,7 @@ - PPD API + PPD API (DEPRECATED) @@ -354,7 +354,9 @@ div.contents ul.subcontents li { file is missing or damaged, see the license at "http://www.cups.org/". --> -

      PPD API

      +

      PPD API (DEPRECATED)

      + +
      The PPD API is deprecated starting in CUPS 1.6. Please use the new Job Ticket APIs in the CUPS API documentation. These functions will be removed in a future release of CUPS.
  • @@ -500,6 +502,8 @@ conflicts.">ppdMarkOption

    Overview

    +
    The PPD API is deprecated starting in CUPS 1.6. Please use the new Job Ticket APIs in the CUPS API documentation. These functions will be removed in a future release of CUPS.
    +

    The CUPS PPD API provides read-only access the data in PostScript Printer Description ("PPD") files which are used for all printers with a driver. With it you can obtain the data necessary to display printer options to users, mark diff --git a/doc/help/man-ipptool.html b/doc/help/man-ipptool.html new file mode 100644 index 000000000..ce090951d --- /dev/null +++ b/doc/help/man-ipptool.html @@ -0,0 +1,144 @@ + + + + + + ipptool(1) + + +

    ipptool(1)

    +

    Name

    +ipptool - perform internet printing protocol requests +

    Synopsis

    +ipptool +[ -4 ] [ -6 ] [ -C ] [ -E ] [ -I ] [ -L ] [ -S ] [ -T +seconds +] [ -V +version +] [ -X ] [ -c ] [ -d +name=value +] [ -f +filename +] [ -i +seconds +] [ -n +repeat-count +] [ -q ] [ -t ] [ -v ] +URI +filename +[ +... filenameN +] +

    Description

    +ipptool sends IPP requests to the specified URI and tests and/or displays the results. Each named file defines one or more requests, including the expected response status, attributes, and values. Output is either a plain text, formatted text, CSV, or XML report on the standard output, with a non-zero exit status indicating that one or more tests have failed. The file format is described in ipptoolfile(5). +

    Options

    +The following options are recognized by ipptool: +
    +
    -4 +
    +
    Specifies that ipptool must connect to the printer or server using IPv4. +
    +
    -6 +
    +
    Specifies that ipptool must connect to the printer or server using IPv6. +
    +
    -C +
    +
    Specifies that requests should be sent using the HTTP/1.1 "Transfer-Encoding: chunked" header, which is required for conformance by all versions of IPP. The default is to use "Transfer-Encoding: chunked" for requests with attached files and "Content-Length:" for requests without attached files. +
    +
    -E +
    +
    Forces TLS encryption when connecting to the server using the HTTP "Upgrade" header. +
    +
    -I +
    +
    Specifies that ipptool will continue past errors. +
    +
    -L +
    +
    Specifies that requests should be sent using the HTTP/1.0 "Content-Length:" header, which is required for conformance by all versions of IPP. The default is to use "Transfer-Encoding: chunked" for requests with attached files and "Content-Length:" for requests without attached files. +
    +
    -S +
    +
    Forces (dedicated) SSL encryption when connecting to the server. +
    +
    -T seconds +
    +
    Specifies a timeout for IPP requests in seconds. +
    +
    -V version +
    +
    Specifies the default IPP version to use: 1.0, 1.1, 2.0, 2.1, or 2.2. If not specified, version 1.1 is used. +
    +
    -X +
    +
    Specifies that XML (Apple plist) output is desired instead of the plain text report. This option is incompatible with the -i (interval) and -n (repeat-count) options. +
    +
    -c +
    +
    Specifies that CSV (comma-separated values) output is desired instead of the plain text output. +
    +
    -d name=value +
    +
    Defines the named variable. +
    +
    -f filename +
    +
    Defines the default request filename for tests. +
    +
    -i seconds +
    +
    Specifies that the (last) file should be repeated at the specified interval. This option is incompatible with the -X (XML plist output) option. +
    +
    -l +
    +
    Specifies that plain text output is desired. +
    +
    -n repeat-count +
    +
    Specifies that the (last) file should be repeated the specified number of times. This option is incompatible with the -X (XML plist output) option. +
    +
    -t +
    +
    Specifies that CUPS test report output is desired instead of the plain text output. +
    +
    -v +
    +
    Specifies that all request and response attributes should be output in CUPS test mode (-t). This is the default for XML output. +
    +
    +

    Compatibility

    +The ipptool program is unique to CUPS. +

    Examples

    +Get a list of completed jobs for "myprinter": +
    +    ipptool ipp://localhost/printers/myprinter get-completed-jobs.test
    +
    +

    Send email notifications to "user@example.com" when "myprinter" changes: +

    +    ipptool -d recipient=mailto:user@example.com 
    +        ipp://localhost/printers/myprinter create-printer-subscription.test
    +
    +

    Standard Files

    +The following standard files are available: +
    +    create-printer-subscription.test
    +    get-completed-jobs.test
    +    get-jobs.test
    +    ipp-1.1.test
    +    ipp-2.0.test
    +    ipp-2.1.test
    +    testfile.jpg
    +    testfile.pdf
    +    testfile.ps
    +    testfile.txt
    +
    +

    See Also

    +ipptoolfile(5), +
    +http://localhost:631/help +

    Copyright

    +Copyright 2007-2010 by Apple Inc. + + + diff --git a/doc/help/man-ipptoolfile.html b/doc/help/man-ipptoolfile.html new file mode 100644 index 000000000..baab6fefb --- /dev/null +++ b/doc/help/man-ipptoolfile.html @@ -0,0 +1,607 @@ + + + + + + ipptoolfile(5) + + +

    ipptoolfile(5)

    +

    Name

    +ipptoolfile - ipptool file format + +

    Description

    +The ipptool(1) program accepts free-form plain text files that describe one or more IPP requests. Comments start with the "#" character and continue to the end of the line. Each request is enclosed by curley braces, for example: +
    +
    +    # This is a comment
    +    {
    +      # The name of the test
    +      NAME "Print PostScript Job"
    +
    +      # The request to send
    +      OPERATION Print-Job
    +      GROUP operation-attributes-tag
    +      ATTR charset attributes-charset utf-8
    +      ATTR language attributes-natural-language en
    +      ATTR uri printer-uri $uri
    +      ATTR name requesting-user-name $user
    +      FILE testfile.ps
    +
    +      # The response to expect
    +      STATUS successful-ok
    +      EXPECT attributes-charset OF-TYPE charset
    +      EXPECT attributes-natural-language OF-TYPE naturalLanguage
    +      EXPECT job-id OF-TYPE integer
    +      EXPECT job-uri OF-TYPE uri
    +    }
    +    {
    +      # The name of the test
    +      NAME "Get Attributes of PostScript Job"
    +
    +      # The request to send
    +      OPERATION Get-Job-Attributes
    +      GROUP operation-attributes-tag
    +      ATTR charset attributes-charset utf-8
    +      ATTR language attributes-natural-language en
    +      ATTR uri printer-uri $uri
    +      ATTR integer job-id $job-id
    +      ATTR name requesting-user-name $user
    +
    +      # The response to expect
    +      STATUS successful-ok
    +      EXPECT attributes-charset OF-TYPE charset
    +      EXPECT attributes-natural-language OF-TYPE naturalLanguage
    +      EXPECT job-id OF-TYPE integer
    +      EXPECT job-uri OF-TYPE uri
    +      EXPECT job-state OF-TYPE enum
    +      EXPECT job-originating-user-name OF-TYPE name WITH-VALUE "$user"
    +    }
    +
    + +

    Top-level Directives

    +The following directives can be used outside of a test: +
    +
    { test } +
    +
    Defines a test. +
    +
    DEFINE variable-name value +
    +
    Defines the named variable to the given value. This is equivalent to specifying +"-d variable-name=value" on the ipptool command-line. +
    +
    DEFINE-DEFAULT variable-name value +
    +
    Defines the named variable to the given value if it does not already have a +value. +
    +
    IGNORE-ERRORS yes +
    +
    +
    IGNORE-ERRORS no +
    +
    Specifies whether, by default, ipptool will ignore errors and continue with +subsequent tests. +
    +
    INCLUDE "filename" +
    +
    +
    INCLUDE <filename> +
    +
    Includes another test file. The first form includes a file relative to the +current test file, while the second form includes a file from the ipptool +include directory. +
    +
    INCLUDE-IF-DEFINED name "filename" +
    +
    +
    INCLUDE-IF-DEFINED name <filename> +
    +
    Includes another test file if the named variable is defined. The first form +includes a file relative to the current test file, while the second form +includes a file from the ipptool include directory. +
    +
    INCLUDE-IF-NOT-DEFINED name "filename" +
    +
    +
    INCLUDE-IF-NOT-DEFINED name <filename> +
    +
    Includes another test file if the named variable is not defined. The first form +includes a file relative to the current test file, while the second form +includes a file from the ipptool include directory. +
    +
    SKIP-IF-DEFINED variable-name +
    +
    +
    SKIP-IF-NOT-DEFINED variable-name +
    +
    Specifies that the remainder of the test file should be skipped when the +variable is or is not defined. +
    +
    TRANSFER auto +
    +
    Specifies that tests will, by default, use "Transfer-Encoding: chunked" for +requests with attached files and "Content-Length:" for requests without attached +files. +
    +
    TRANSFER chunked +
    +
    Specifies that tests will, by default, use the HTTP/1.1 "Transfer-Encoding: +chunked" header. This is the default and is equivalent to specifying "-c" on the +ipptool command-line. Support for chunked requests is required for +conformance with all versions of IPP. +
    +
    TRANSFER length +
    +
    Specifies that tests will, by default, use the HTTP/1.0 "Content-Length:" +header. This is equivalent to specifying "-l" on the ipptool command-line. +Support for content length requests is required for conformance with all +versions of IPP. +
    +
    VERSION 1.0 +
    +
    +
    VERSION 1.1 +
    +
    +
    VERSION 2.0 +
    +
    +
    VERSION 2.1 +
    +
    +
    VERSION 2.2 +
    +
    Specifies the default IPP version number to use for the tests that follow. + +
    +
    +

    Test Directives

    +The following directives are understood in a test: +
    +
    ATTR tag attribute-name value(s) +
    +
    Adds an attribute to the test request. Values are separated by the comma (",") +character - escape commas using the "" character. +
    +
    ATTR collection attribute-name { MEMBER tag member-name value(s) ... } [ ... { ... } ] +
    +
    Adds a collection attribute to the test request. Member attributes follow the +same syntax as regular attributes and can themselves be nested collections. +Multiple collection values can be supplied as needed. +
    +
    DELAY seconds +
    +
    Specifies a delay before this test will be run. +
    +
    DISPLAY attribute-name +
    +
    Specifies that value of the named attribute should be output as part of the +test report. +
    +
    EXPECT attribute-name [ predicate(s) ] +
    +
    +
    EXPECT ?attribute-name predicate(s) +
    +
    +
    EXPECT !attribute-name +
    +
    Specifies that the response must/may/must not include the named attribute. +Additional requirements can be added as predicates - see the "EXPECT PREDICATES" +section for more information on predicates. +
    +
    FILE filename +
    +
    Specifies a file to include at the end of the request. This is typically used +when sending a test print file. +
    +
    GROUP tag +
    +
    Specifies the group tag for subsequent attributes in the request. +
    +
    IGNORE-ERRORS yes +
    +
    +
    IGNORE-ERRORS no +
    +
    Specifies whether ipptool will ignore errors and continue with subsequent +tests. +
    +
    NAME "literal string" +
    +
    Specifies the human-readable name of the test. +
    +
    OPERATION operation-code +
    +
    Specifies the operation to be performed. +
    +
    REQUEST-ID number +
    +
    +
    REQUEST-ID random +
    +
    Specifies the request-id value to use in the request, either an integer or the +word "random" to use a randomly generated value (the default). +
    +
    RESOURCE path +
    +
    Specifies an alternate resource path that is used for the HTTP POST request. +The default is the resource from the URI provided to the ipptool program. +
    +
    SKIP-IF-DEFINED variable-name +
    +
    +
    SKIP-IF-NOT-DEFINED variable-name +
    +
    Specifies that the current test should be skipped when the variable is or is not +defined. +
    +
    SKIP-PREVIOUS-ERROR yes +
    +
    +
    SKIP-PREVIOUS-ERROR no +
    +
    Specifies whether ipptool will skip the current test if the previous test +resulted in an error/failure. +
    +
    STATUS status-code [ predicate ] +
    +
    Specifies an expected response status-code value. Additional requirements can be +added as predicates - see the "STATUS PREDICATES" section for more information +on predicates. +
    +
    TRANSFER auto +
    +
    Specifies that this test will use "Transfer-Encoding: chunked" if it has an +attached file or "Content-Length:" otherwise. +
    +
    TRANSFER chunked +
    +
    Specifies that this test will use the HTTP/1.1 "Transfer-Encoding: chunked" +header. +
    +
    TRANSFER length +
    +
    Specifies that this test will use the HTTP/1.0 "Content-Length:" header. +
    +
    VERSION 1.0 +
    +
    +
    VERSION 1.1 +
    +
    +
    VERSION 2.0 +
    +
    +
    VERSION 2.1 +
    +
    +
    VERSION 2.2 +
    +
    Specifies the IPP version number to use for this test. + +
    +
    +

    Expect Predicates

    +The following predicates are understood following the EXPECT test directive: +
    +
    COUNT number +
    +
    Requires the EXPECT attribute to have the specified number of values. +
    +
    DEFINE-MATCH variable-name +
    +
    Defines the variable to "1" when the EXPECT condition matches. A side-effect of +this predicate is that this EXPECT will never fail a test. +
    +
    DEFINE-NO-MATCH variable-name +
    +
    Defines the variable to "1" when the EXPECT condition does not match. A side- +effect of this predicate is that this EXPECT will never fail a test. +
    +
    DEFINE-VALUE variable-name +
    +
    Defines the variable to the value of the attribute when the EXPECT condition +matches. A side-effect of this predicate is that this EXPECT will never fail a test. +
    +
    IF-DEFINED variable-name +
    +
    Makes the EXPECT conditions apply only if the specified variable is defined. +
    +
    IF-NOT-DEFINED variable-name +
    +
    Makes the EXPECT conditions apply only if the specified variable is not +defined. +
    +
    IN-GROUP tag +
    +
    Requires the EXPECT attribute to be in the specified group tag. +
    +
    OF-TYPE tag[,tag,...] +
    +
    Requires the EXPECT attribute to use the specified value tag(s). +
    +
    REPEAT-MATCH +
    +
    +
    REPEAT-NO-MATCH +
    +
    Specifies that the current test should be repeated when the EXPECT condition +matches or does not match. +
    +
    SAME-COUNT-AS attribute-name +
    +
    Requires the EXPECT attribute to have the same number of values as the specified +parallel attribute. +
    +
    WITH-VALUE "literal string" +
    +
    Requires at least one value of the EXPECT attribute to match the literal string. +Comparisons are case-sensitive. +
    +
    WITH-VALUE "/regular expression/" +
    +
    Requires that all values of the EXPECT attribute match the regular expression, +which must conform to the POSIX regular expression syntax. +Comparisons are case-sensitive. + +
    +
    +

    Status Predicates

    +The following predicates are understood following the STATUS test directive: +
    +
    IF-DEFINED variable-name +
    +
    Makes the STATUS apply only if the specified variable is defined. +
    +
    IF-NOT-DEFINED variable-name +
    +
    Makes the STATUS apply only if the specified variable is not defined. +
    +
    REPEAT-MATCH +
    +
    +
    REPEAT-NO-MATCH +
    +
    Specifies that the current test should be repeated when the response status-code +matches or does not match the value specified by the STATUS directive. + +
    +
    +

    Operation Codes

    +Operation codes correspond to the hexadecimal numbers (0xHHHH) and names from +RFC 2911 and other IPP extension specifications. Here is a complete list: +
    +    Activate-Printer
    +    CUPS-Accept-Jobs
    +    CUPS-Add-Modify-Class
    +    CUPS-Add-Modify-Printer
    +    CUPS-Authenticate-Job
    +    CUPS-Delete-Class
    +    CUPS-Delete-Printer
    +    CUPS-Get-Classes
    +    CUPS-Get-Default
    +    CUPS-Get-Devices
    +    CUPS-Get-Document
    +    CUPS-Get-PPD
    +    CUPS-Get-PPDs
    +    CUPS-Get-Printers
    +    CUPS-Move-Job
    +    CUPS-Reject-Jobs
    +    CUPS-Set-Default
    +    Cancel-Current-Job
    +    Cancel-Job
    +    Cancel-Jobs
    +    Cancel-My-Jobs
    +    Cancel-Subscription
    +    Close-Job
    +    Create-Job
    +    Create-Job-Subscription
    +    Create-Printer-Subscription
    +    Deactivate-Printer
    +    Disable-Printer
    +    Enable-Printer
    +    Get-Job-Attributes
    +    Get-Jobs
    +    Get-Notifications
    +    Get-Printer-Attributes
    +    Get-Printer-Support-Files
    +    Get-Printer-Supported-Values
    +    Get-Subscription-Attributes
    +    Get-Subscriptions
    +    Hold-Job
    +    Hold-New-Jobs
    +    Pause-Printer
    +    Pause-Printer-After-Current-Job
    +    Print-Job
    +    Print-URI
    +    Promote-Job
    +    Purge-Jobs
    +    Release-Held-New-Jobs
    +    Release-Job
    +    Renew-Subscription
    +    Reprocess-Job
    +    Restart-Job
    +    Restart-Printer
    +    Resubmit-Job
    +    Resume-Job
    +    Resume-Printer
    +    Schedule-Job-After
    +    Send-Document
    +    Send-Notifications
    +    Send-URI
    +    Set-Job-Attributes
    +    Set-Printer-Attributes
    +    Shutdown-Printer
    +    Startup-Printer
    +    Suspend-Current-Job
    +    Validate-Job
    +
    + +

    Status Codes

    +Status codes correspond to the hexadecimal numbers (0xHHHH) and names from RFC +2911 and other IPP extension specifications. Here is a complete list: +
    +    client-error-attributes-not-settable
    +    client-error-attributes-or-values-not-supported
    +    client-error-bad-request
    +    client-error-charset-not-supported
    +    client-error-compression-error
    +    client-error-compression-not-supported
    +    client-error-conflicting-attributes
    +    client-error-document-access-error
    +    client-error-document-format-error
    +    client-error-document-format-not-supported
    +    client-error-forbidden
    +    client-error-gone
    +    client-error-ignored-all-notifications
    +    client-error-ignored-all-subscriptions
    +    client-error-not-authenticated
    +    client-error-not-authorized
    +    client-error-not-found
    +    client-error-not-possible
    +    client-error-print-support-file-not-found
    +    client-error-request-entity-too-large
    +    client-error-request-value-too-long
    +    client-error-timeout
    +    client-error-too-many-subscriptions
    +    client-error-uri-scheme-not-supported
    +    cups-see-other
    +    redirection-other-site
    +    server-error-busy
    +    server-error-device-error
    +    server-error-internal-error
    +    server-error-job-canceled
    +    server-error-multiple-document-jobs-not-supported
    +    server-error-not-accepting-jobs
    +    server-error-operation-not-supported
    +    server-error-printer-is-deactivated
    +    server-error-service-unavailable
    +    server-error-temporary-error
    +    server-error-version-not-supported
    +    successful-ok
    +    successful-ok-but-cancel-subscription
    +    successful-ok-conflicting-attributes
    +    successful-ok-events-complete
    +    successful-ok-ignored-notifications
    +    successful-ok-ignored-or-substituted-attributes
    +    successful-ok-ignored-subscriptions
    +    successful-ok-too-many-events
    +
    + +

    Tags

    +Value and group tags correspond to the names from RFC 2911 and other IPP +extension specifications. Here are the group tags: +
    +    event-notification-attributes-tag
    +    job-attributes-tag
    +    operation-attributes-tag
    +    printer-attributes-tag
    +    subscription-attributes-tag
    +    unsupported-attributes-tag
    +
    +

    Here are the value tags: +

    +    admin-define
    +    boolean
    +    charset
    +    collection
    +    dateTime
    +    default
    +    delete-attribute
    +    enum
    +    integer
    +    keyword
    +    mimeMediaType
    +    nameWithLanguage
    +    nameWithoutLanguage
    +    naturalLanguage
    +    no-value
    +    not-settable
    +    octetString
    +    rangeOfInteger
    +    resolution
    +    textWithLanguage
    +    textWithoutLanguage
    +    unknown
    +    unsupported
    +    uri
    +    uriScheme
    +
    + +

    Variables

    +The ipptool program maintains a list of variables that can be used in any +literal string or attribute value by specifying "$variable-name". Aside from +variables defined using the "-d" option or "DEFINE" directive, the following +pre-defined variables are available: +
    +
    $$ +
    +
    Inserts a single "$" character. +
    +
    $ENV[name] +
    +
    Inserts the value of the named environment variable, or an empty string if the +environment variable is not defined. +
    +
    $filename +
    +
    Inserts the filename provided to ipptool with the "-f" option. +
    +
    $hostname +
    +
    Inserts the hostname from the URI provided to ipptool. +
    +
    $job-id +
    +
    Inserts the last job-id value returned in a test response or 0 if no job-id has +been seen. +
    +
    $job-uri +
    +
    Inserts the last job-uri value returned in a test response or an empty string if +no job-uri has been seen. +
    +
    $scheme +
    +
    Inserts the scheme from the URI provided to ipptool. +
    +
    $notify-subscription-id +
    +
    Inserts the last notify-subscription-id value returnd in a test response or 0 if +no notify-subscription-id has been seen. +
    +
    $port +
    +
    Inserts the port number from the URI provided to ipptool. +
    +
    $resource +
    +
    Inserts the resource path from the URI provided to ipptool. +
    +
    $uri +
    +
    Inserts the URI provided to ipptool. +
    +
    $user +
    +
    Inserts the current user's login name. +
    +
    $username +
    +
    Inserts the username from the URI provided to ipptool, if any. + +
    +
    +

    See Also

    +ipptool(1), +
    +http://localhost:631/help + +

    Copyright

    +Copyright 2007-2011 by Apple Inc. + + + diff --git a/doc/help/ref-cupsd-conf.html.in b/doc/help/ref-cupsd-conf.html.in index 6002729cf..36f694a32 100644 --- a/doc/help/ref-cupsd-conf.html.in +++ b/doc/help/ref-cupsd-conf.html.in @@ -335,229 +335,6 @@ quotas. This option has no effect if quotas are not enabled. The default setting is No.

    -

    BrowseAddress

    - -

    Examples

    - -
    -BrowseAddress 255.255.255.255:631
    -BrowseAddress 192.0.2.255:631
    -BrowseAddress host.example.com:631
    -BrowseAddress @LOCAL
    -BrowseAddress @IF(name)
    -
    - -

    Description

    - -

    The BrowseAddress directive specifies an address -to send browsing information to. Multiple -BrowseAddress directives can be specified to send -browsing information to different networks or systems.

    - -

    The @LOCAL name will broadcast printer -information to all local interfaces. The @IF(name) -name will broadcast to the named interface.

    - -

    There is no default browse address.

    - -
    Note: - -

    If you are using HP-UX 10.20 and a subnet that is not 24, -16, or 8 bits, printer browsing (and in fact all broadcast -reception) will not work. This problem appears to be fixed in -HP-UX 11.0.

    - -
    - - -

    BrowseAllow

    - -

    Examples

    - -
    -BrowseAllow from all
    -BrowseAllow from none
    -BrowseAllow from 192.0.2
    -BrowseAllow from 192.0.2.0/24
    -BrowseAllow from 192.0.2.0/255.255.255.0
    -BrowseAllow from *.example.com
    -BrowseAllow from @LOCAL
    -BrowseAllow from @IF(name)
    -
    - -

    Description

    - -

    The BrowseAllow directive specifies a system or -network to accept browse packets from. The default is to accept -browse packets from all hosts.

    - -

    Host and domain name matching require that you enable the HostNameLookups -directive.

    - -

    IP address matching supports exact matches, partial addresses that match -networks using netmasks of 255.0.0.0, 255.255.0.0, and 255.255.255.0, or network -addresses using the specified netmask or bit count. The /mm -notation specifies a CIDR netmask, a shown in Table 1.

    - -

    The @LOCAL name will allow browse data from all -local interfaces. The @IF(name) name will allow -browse data from the named interface. In both cases, CUPS only -allows data from the network that the interface(s) are configured -for - data arriving on the interface from a foreign network will -not be allowed.

    - - -

    BrowseDeny

    - -

    Examples

    - -
    -BrowseDeny from all
    -BrowseDeny from none
    -BrowseDeny from 192.0.2
    -BrowseDeny from 192.0.2.0/24
    -BrowseDeny from 192.0.2.0/255.255.255.0
    -BrowseDeny from *.example.com
    -BrowseDeny from @LOCAL
    -BrowseDeny from @IF(name)
    -
    - -

    Description

    - -

    The BrowseDeny directive specifies a system or -network to reject browse packets from. The default is to not deny -browse packets from any hosts.

    - -

    Host and domain name matching require that you enable the HostNameLookups -directive.

    - -

    IP address matching supports exact matches, partial addresses that match -networks using netmasks of 255.0.0.0, 255.255.0.0, and 255.255.255.0, or network -addresses using the specified netmask or bit count. The /mm -notation specifies a CIDR netmask, a shown in Table 1.

    - -

    The @LOCAL name will block browse data from all -local interfaces. The @IF(name) name will block -browse data from the named interface. In both cases, CUPS only -blocks data from the network that the interface(s) are configured -for - data arriving on the interface from a foreign network will -not be blocked.

    - - -

    BrowseInterval

    - -

    Examples

    - -
    -BrowseInterval 0
    -BrowseInterval 30
    -
    - -

    Description

    - -

    The BrowseInterval directive specifies the -maximum amount of time between browsing updates. Specifying a -value of 0 seconds disables outgoing browse updates but allows a -server to receive printer information from other hosts.

    - -

    The BrowseInterval value should always be less -than the BrowseTimeout -value. Otherwise printers and classes will disappear from client -systems between updates.

    - - -

    CUPS 1.2/Mac OS X 10.5BrowseLDAPBindDN

    - -

    Examples

    - -
    -BrowseLDAPBindDN foo
    -
    - -

    Description

    - -

    The BrowseLDAPBindDN directive specifies the LDAP -domain name to use when listening for printer registrations. The -default is undefined.

    - - -

    CUPS 1.4/Mac OS X 10.6BrowseLDAPCACertFile

    - -

    Examples

    - -
    -BrowseLDAPCACertFile /etc/cups/ssl/certs
    -
    - -

    Description

    - -

    The BrowseLDAPCACertFile directive specifies the SSL certificate -authority file to use for LDAP + SSL. The default is undefined.

    - - -

    CUPS 1.2/Mac OS X 10.5BrowseLDAPDN

    - -

    Examples

    - -
    -BrowseLDAPDN bar
    -
    - -

    Description

    - -

    The BrowseLDAPDN directive specifies the LDAP -domain name to use when registering local shared printers. The -default is undefined.

    - - -

    CUPS 1.2/Mac OS X 10.5BrowseLDAPPassword

    - -

    Examples

    - -
    -BrowseLDAPPassword foo123
    -
    - -

    Description

    - -

    The BrowseLDAPPassword directive specifies the -access password to use when connecting to the LDAP server. The -default is undefined.

    - - -

    CUPS 1.2/Mac OS X 10.5BrowseLDAPServer

    - -

    Examples

    - -
    -BrowseLDAPServer localhost
    -
    - -

    Description

    - -

    The BrowseLDAPServer directive specifies the name -of the LDAP server to connect to. The default is undefined.

    - - -

    BrowseLocalOptions

    - -

    Examples

    - -
    -BrowseLocalOptions compression=yes
    -BrowseLocalOptions encryption=required
    -BrowseLocalOptions compression=yes&encryption=required
    -
    - -

    Description

    - -

    The BrowseLocalOptions directive specifies -additional IPP backend options to advertise with local shared -printers. The default is to not include any options.

    - -

    CUPS 1.2/Mac OS X 10.5BrowseLocalProtocols

    Examples

    @@ -565,13 +342,7 @@ printers. The default is to not include any options.

     BrowseLocalProtocols all
     BrowseLocalProtocols none
    -BrowseLocalProtocols cups
     BrowseLocalProtocols dnssd
    -BrowseLocalProtocols ldap
    -BrowseLocalProtocols lpd
    -BrowseLocalProtocols slp
    -BrowseLocalProtocols smb
    -BrowseLocalProtocols cups dnssd
     

    Description

    @@ -582,230 +353,6 @@ network. Multiple protocols can be specified by separating them with spaces. The default is "@CUPS_BROWSE_LOCAL_PROTOCOLS@".

    -

    BrowseOrder

    - -

    Examples

    - -
    -BrowseOrder allow,deny
    -BrowseOrder deny,allow
    -
    - -

    Description

    - -

    The BrowseOrder directive specifies the order of -allow/deny processing. The default order is -deny,allow:

    - -
      - -
    • allow,deny - Deny browse packets by - default, then check BrowseAllow lines - followed by BrowseDeny lines.
    • - -
    • deny,allow - Allow browse packets by - default, then check BrowseDeny lines - followed by BrowseAllow lines.
    • - -
    - - -

    BrowsePoll

    - -

    Examples

    - -
    -BrowsePoll 192.0.2.2:631
    -BrowsePoll host.example.com:631
    -
    - -

    Description

    - -

    The BrowsePoll directive polls a server for -available printers once every BrowseInterval seconds. -Multiple BrowsePoll directives can be specified to -poll multiple servers.

    - -

    If BrowseInterval is set to 0 then the server is -polled once every 30 seconds.

    - - -

    BrowsePort

    - -

    Examples

    - -
    -BrowsePort 631
    -BrowsePort 9999
    -
    - -

    Description

    - -

    The BrowsePort directive specifies the UDP port number -used for browse packets. The default port number is 631.

    - -
    Note: - -

    You must set the BrowsePort to the same value -on all of the systems that you want to see. - -

    - - -

    CUPS 1.1.10BrowseProtocols

    - -

    Examples

    - -
    -BrowseProtocols all
    -BrowseProtocols none
    -BrowseProtocols cups
    -BrowseProtocols dnssd
    -BrowseProtocols ldap
    -BrowseProtocols lpd
    -BrowseProtocols slp
    -BrowseProtocols smb
    -BrowseProtocols cups dnssd
    -
    - -

    Description

    - -

    The BrowseProtocols directive specifies the -protocols to use when showing and advertising shared printers on -the local network. Multiple protocols can be specified by -separating them with spaces. The default protocol is -"@CUPS_BROWSE_LOCAL_PROTOCOLS@" for -BrowseLocalProtocols and -"@CUPS_BROWSE_REMOTE_PROTOCOLS@" for -BrowseRemoteProtocols.

    - -
    Note: - -

    When using the SLP protocol, you must have at least -one Directory Agent (DA) server on your network. Otherwise the -CUPS scheduler (cupsd) will not respond to client -requests for several seconds while polling the network.

    - -
    - - -

    BrowseRelay

    - -

    Examples

    - -
    -BrowseRelay 193.0.2.1 192.0.2.255
    -BrowseRelay 193.0.2.0/255.255.255.0 192.0.2.255
    -BrowseRelay 193.0.2.0/24 192.0.2.255
    -BrowseRelay *.example.com 192.0.2.255
    -BrowseRelay host.example.com 192.0.2.255
    -
    - -

    Description

    - -

    The BrowseRelay directive specifies source and -destination addresses for relaying browsing information from one -host or network to another. Multiple BrowseRelay -directives can be specified as needed.

    - -

    BrowseRelay is typically used on systems that -bridge multiple subnets using one or more network interfaces. It -can also be used to relay printer information from polled servers -with the line:

    - -
    -BrowseRelay 127.0.0.1 192.0.2.255
    -
    - -

    This effectively provides access to printers on a WAN for all -clients on the LAN. Use multiple BrowseRelay lines to -relay information to multiple subnets.

    - - -

    BrowseRemoteOptions

    - -

    Examples

    - -
    -BrowseRemoteOptions compression=yes
    -BrowseRemoteOptions encryption=required
    -BrowseRemoteOptions ?compression=yes&encryption=required
    -
    - -

    Description

    - -

    The BrowseRemoteOptions directive specifies -additional IPP backend options to include with remote shared -printers. If the options string begins with a question mark (?), -the options replace any options specified by the remote server. -The default is to not include any options.

    - - -

    CUPS 1.2/Mac OS X 10.5BrowseRemoteProtocols

    - -

    Examples

    - -
    -BrowseRemoteProtocols all
    -BrowseRemoteProtocols none
    -BrowseRemoteProtocols cups
    -BrowseRemoteProtocols ldap
    -BrowseRemoteProtocols slp
    -
    - -

    Description

    - -

    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 "@CUPS_BROWSE_REMOTE_PROTOCOLS@".

    - - -

    BrowseShortNames

    - -

    Examples

    - -
    -BrowseShortNames Yes
    -BrowseShortNames No
    -
    - -

    Description

    - -

    The BrowseShortNames directive specifies whether -or not short names are used for remote printers when possible. -Short names are just the remote printer name, without the server -("printer"). If more than one remote printer is detected with the -same name, the printers will have long names ("printer@server1", -"printer@server2".)

    - -

    The default value for this option is @CUPS_BROWSE_SHORT_NAMES@.

    - - -

    BrowseTimeout

    - -

    Examples

    - -
    -BrowseTimeout 300
    -BrowseTimeout 60
    -
    - -

    Description

    - -

    The BrowseTimeout directive sets the timeout for -printer or class information that is received in browse packets. -Once a printer or class times out it is removed from the list of -available destinations.

    - -

    The BrowseTimeout value should always be greater -than the BrowseInterval value. -Otherwise printers and classes will disappear from client systems -between updates.

    - -

    BrowseWebIF

    Examples

    @@ -834,24 +381,9 @@ Browsing Off

    Description

    The Browsing directive controls whether or not -network printer browsing is enabled. The default setting is +printer sharing is enabled. The default setting is @CUPS_BROWSING@.

    -

    This directive does not enable sharing of local printers by -itself; you must also use the BrowseAddress or BrowseProtocols -directives to advertise local printers to other systems.

    - -
    Note: - -

    If you are using HP-UX 10.20 and a subnet that is not 24, -16, or 8 bits, printer browsing (and in fact all broadcast -reception) will not work. This problem appears to be fixed in -HP-UX 11.0.

    - -
    -

    CUPS 1.1.7Classification

    @@ -1382,25 +914,6 @@ system-specific but is usually lp or nobody.

    -

    CUPS 1.1.10HideImplicitMembers

    - -

    Examples

    - -
    -HideImplicitMembers Yes
    -HideImplicitMembers No
    -
    - -

    Description

    - -

    The HideImplicitMembers directive controls -whether the individual printers in an implicit class are hidden -from the user. The default is Yes.

    - -

    ImplicitClasses -must be enabled for this directive to have any effect.

    - -

    HostNameLookups

    Examples

    @@ -1427,45 +940,6 @@ performance problems with hostname lookups. Set this option to required.

    -

    CUPS 1.1.10ImplicitAnyClasses

    - -

    Examples

    - -
    -ImplicitAnyClasses On
    -ImplicitAnyClasses Off
    -
    - -

    Description

    - -

    The ImplicitAnyClasses directive controls -whether implicit classes for local and remote printers are -created with the name AnyPrinter. The default -setting is Off.

    - -

    ImplicitClasses -must be enabled for this directive to have any effect.

    - - -

    ImplicitClasses

    - -

    Examples

    - -
    -ImplicitClasses On
    -ImplicitClasses Off
    -
    - -

    Description

    - -

    The ImplicitClasses directive controls whether -implicit classes are created based upon the available network -printers and classes. The default setting is -@CUPS_IMPLICIT_CLASSES@ but is automatically turned -Off if Browsing is turned -Off.

    - -

    CUPS 1.1.9Include

    Examples

    diff --git a/doc/help/ref-page_log.html b/doc/help/ref-page_log.html index 076cc4b9c..46453eb2e 100644 --- a/doc/help/ref-page_log.html +++ b/doc/help/ref-page_log.html @@ -23,7 +23,7 @@ DeskJet root 2 [20/May/1999:19:21:05 +0000] 2 1 acme-123 localhost myjob letter

    -

    The PageLogFormat +

    The PageLogFormat directive can be used to change this information.

    The printer field contains the name of the printer that diff --git a/filter/interpret.c b/filter/interpret.c index eed4432d8..0c03edf68 100644 --- a/filter/interpret.c +++ b/filter/interpret.c @@ -1387,7 +1387,7 @@ setpagedevice( * Found the start of the dictionary, empty the stack to this point... */ - st->num_objs = obj - st->objs; + st->num_objs = (int)(obj - st->objs); /* * Now pull /name and value pairs from the dictionary... diff --git a/filter/raster.c b/filter/raster.c index bb5725206..dd3ef5a30 100644 --- a/filter/raster.c +++ b/filter/raster.c @@ -504,7 +504,7 @@ cupsRasterReadPixels(cups_raster_t *r, /* I - Raster stream */ * Copy fragment from buffer... */ - if ((unsigned)(bytes = r->pend - r->pcurrent) > remaining) + if ((unsigned)(bytes = (int)(r->pend - r->pcurrent)) > remaining) bytes = remaining; memcpy(p, r->pcurrent, bytes); @@ -830,8 +830,8 @@ cupsRasterWritePixels(cups_raster_t *r, /* I - Raster stream */ * Figure out the number of remaining bytes on the current line... */ - if ((bytes = remaining) > (r->pend - r->pcurrent)) - bytes = r->pend - r->pcurrent; + if ((bytes = remaining) > (int)(r->pend - r->pcurrent)) + bytes = (int)(r->pend - r->pcurrent); if (r->count > 0) { @@ -1047,8 +1047,10 @@ cups_raster_read(cups_raster_t *r, /* I - Raster stream */ if ((size_t)count > r->bufsize) { - int offset = r->bufptr - r->buffer; /* Offset to current start of buffer */ - int end = r->bufend - r->buffer; /* Offset to current end of buffer */ + int offset = (int)(r->bufptr - r->buffer); + /* Offset to current start of buffer */ + int end = (int)(r->bufend - r->buffer); + /* Offset to current end of buffer */ unsigned char *rptr; /* Pointer in read buffer */ if (r->buffer) @@ -1069,7 +1071,7 @@ cups_raster_read(cups_raster_t *r, /* I - Raster stream */ * Loop until we have read everything... */ - for (total = 0, remaining = r->bufend - r->bufptr; + for (total = 0, remaining = (int)(r->bufend - r->bufptr); total < bytes; total += count, buf += count) { @@ -1387,7 +1389,7 @@ cups_raster_write( } } - return (cups_raster_io(r, r->buffer, wptr - r->buffer)); + return (cups_raster_io(r, r->buffer, (int)(wptr - r->buffer))); } @@ -1405,7 +1407,11 @@ cups_read_fd(void *ctx, /* I - File descriptor as pointer */ ssize_t count; /* Number of bytes read */ +#ifdef WIN32 /* Sigh */ + while ((count = read(fd, buf, (unsigned)bytes)) < 0) +#else while ((count = read(fd, buf, bytes)) < 0) +#endif /* WIN32 */ if (errno != EINTR && errno != EAGAIN) return (-1); @@ -1453,7 +1459,11 @@ cups_write_fd(void *ctx, /* I - File descriptor pointer */ ssize_t count; /* Number of bytes written */ +#ifdef WIN32 /* Sigh */ + while ((count = write(fd, buf, (unsigned)bytes)) < 0) +#else while ((count = write(fd, buf, bytes)) < 0) +#endif /* WIN32 */ if (errno != EINTR && errno != EAGAIN) return (-1); diff --git a/man/cupsd.conf.man.in b/man/cupsd.conf.man.in index c941c02db..aec9905d1 100644 --- a/man/cupsd.conf.man.in +++ b/man/cupsd.conf.man.in @@ -12,7 +12,7 @@ .\" which should have been included with this file. If this file is .\" file is missing or damaged, see the license at "http://www.cups.org/". .\" -.TH cupsd.conf 5 "CUPS" "18 May 2011" "Apple Inc." +.TH cupsd.conf 5 "CUPS" "3 November 2011" "Apple Inc." .SH NAME cupsd.conf \- server configuration file for cups .SH DESCRIPTION @@ -94,121 +94,9 @@ AutoPurgeJobs No Specifies whether to purge job history data automatically when it is no longer required for quotas. .TP 5 -BrowseAddress ip-address -.TP 5 -BrowseAddress @IF(name) -.TP 5 -BrowseAddress @LOCAL -.br -Specifies a broadcast address for outgoing printer information packets. -.TP 5 -BrowseAllow all -.TP 5 -BrowseAllow none -.TP 5 -BrowseAllow host.domain.com -.TP 5 -BrowseAllow *.domain.com -.TP 5 -BrowseAllow ip-address -.TP 5 -BrowseAllow ip-address/netmask -.TP 5 -BrowseAllow ip-address/mm -.TP 5 -BrowseAllow @IF(name) -.TP 5 -BrowseAllow @LOCAL -.br -Allows incoming printer information packets from the named host or address. -.TP 5 -BrowseDeny all -.TP 5 -BrowseDeny none -.TP 5 -BrowseDeny host.domain.com -.TP 5 -BrowseDeny *.domain.com -.TP 5 -BrowseDeny ip-address -.TP 5 -BrowseDeny ip-address/netmask -.TP 5 -BrowseDeny ip-address/mm -.TP 5 -BrowseDeny @IF(name) -.TP 5 -BrowseDeny @LOCAL -.br -Denies incoming printer information packets from the named host or address. -.TP 5 -BrowseInterval seconds -.br -Specifies the maximum interval between printer information broadcasts. -.TP 5 -BrowseLDAPBindDN -.br -Specifies the LDAP domain name to use when registering printers. -.TP 5 -BrowseLDAPCACertFile -.br -Specifies the SSL certificate authority file to use. -.TP 5 -BrowseLDAPDN -.br -Specifies the LDAP domain name to use when discovering printers. -.TP 5 -BrowseLDAPPassword +BrowseLocalProtocols [All] [DNSSD] .br -Specifies the password to use when accessing the LDAP server. -.TP 5 -BrowseLDAPServer -.br -Specifies the LDAP server to use. -.TP 5 -BrowseOrder allow,deny -.TP 5 -BrowseOrder deny,allow -.br -Specifies the order of printer information access control (allow,deny or deny,allow) -.TP 5 -BrowsePoll host-or-ip-address -.br -Specifies a server to poll for printer information. -.TP 5 -BrowsePort port -.br -Specifies the port to listen to for printer information packets. -.TP 5 -BrowseProtocols [All] [CUPS] [DNSSD] [LDAP] [SLP] -.br -Specifies the protocols to use for printer browsing. -.TP 5 -BrowseLocalProtocols [All] [CUPS] [DNSSD] [LDAP] [SLP] -.br -Specifies the protocols to use for local printer browsing. -.TP 5 -BrowseRemoteProtocols [All] [CUPS] [DNSSD] [LDAP] [SLP] -.br -Specifies the protocols to use for remote printer browsing. -.TP 5 -BrowseRelay from-address to-address -.br -Specifies that printer information packets should be relayed from one host or -network to another. -.TP 5 -BrowseShortNames Yes -.TP 5 -BrowseShortNames No -.br -Specifies whether remote printers will use short names ("printer") or not -("printer@server"). This option is ignored if more than one remote printer -exists with the same name. -.TP 5 -BrowseTimeout seconds -.br -Specifies the maximum interval between printer information updates before -remote printers will be removed from the list of available printers. +Specifies the protocols to use for local printer sharing. .TP 5 BrowseWebIF Yes .TP 5 @@ -362,12 +250,6 @@ Group group-name-or-number Specifies the group name or ID that will be used when executing external programs. .TP 5 -HideImplicitMembers Yes -.TP 5 -HideImplicitMembers No -.br -Specifies whether to hide members of implicit classes. -.TP 5 HostNameLookups On .TP 5 HostNameLookups Off @@ -376,21 +258,6 @@ HostNameLookups Double .br Specifies whether or not to do reverse lookups on client addresses. .TP 5 -ImplicitAnyClasses Yes -.TP 5 -ImplicitAnyClasses No -.br -Specifies whether or not to create implicit classes for local and -remote printers, e.g. "AnyPrinter" from "Printer", "Printer@server1", -and "Printer@server2". -.TP 5 -ImplicitClasses Yes -.TP 5 -ImplicitClasses No -.br -Specifies whether or not to create implicit classes from identical -remote printers. -.TP 5 Include filename .br Includes the named file. diff --git a/notifier/mailto.c b/notifier/mailto.c index 7ee15519d..da2db951d 100644 --- a/notifier/mailto.c +++ b/notifier/mailto.c @@ -632,7 +632,7 @@ print_attributes(ipp_t *ipp, /* I - IPP request */ fprintf(stderr, "DEBUG: %*s%s:\n\n", indent - 4, "", ippTagString(group)); } - _ippAttrString(attr, buffer, sizeof(buffer)); + ippAttributeString(attr, buffer, sizeof(buffer)); fprintf(stderr, "DEBUG: %*s%s (%s%s) %s", indent, "", attr->name, attr->num_values > 1 ? "1setOf " : "", diff --git a/notifier/rss.c b/notifier/rss.c index 9c9aa7553..f42c921a2 100644 --- a/notifier/rss.c +++ b/notifier/rss.c @@ -3,7 +3,7 @@ * * RSS notifier for CUPS. * - * Copyright 2007-2010 by Apple Inc. + * Copyright 2007-2011 by Apple Inc. * Copyright 2007 by Easy Software Products. * * These coded instructions, statements, and computer programs are the @@ -33,6 +33,7 @@ #include #include #include +#include /* TODO: Update so we don't need this */ /* diff --git a/notifier/testnotify.c b/notifier/testnotify.c index 7e91f18cb..faa846d08 100644 --- a/notifier/testnotify.c +++ b/notifier/testnotify.c @@ -113,7 +113,7 @@ print_attributes(ipp_t *ipp, /* I - IPP request */ fprintf(stderr, "DEBUG: %*s%s:\n\n", indent - 4, "", ippTagString(group)); } - _ippAttrString(attr, buffer, sizeof(buffer)); + ippAttributeString(attr, buffer, sizeof(buffer)); fprintf(stderr, "DEBUG: %*s%s (%s%s) %s", indent, "", attr->name, attr->num_values > 1 ? "1setOf " : "", diff --git a/scheduler/Makefile b/scheduler/Makefile index d562437a3..c8570be62 100644 --- a/scheduler/Makefile +++ b/scheduler/Makefile @@ -51,8 +51,6 @@ COBJS = \ cups-deviced.o \ cups-exec.o \ cups-lpd.o \ - cups-polld.o \ - testdirsvc.o \ testlpd.o \ testmime.o \ testspeed.o \ @@ -68,7 +66,6 @@ LIBTARGETS = \ libcupsmime.a UNITTARGETS = \ - testdirsvc \ testlpd \ testmime \ testspeed \ @@ -80,8 +77,7 @@ PROGRAMS = \ cups-deviced \ cups-driverd \ cups-exec \ - cups-lpd \ - cups-polld + cups-lpd TARGETS = \ $(LIBTARGETS) \ @@ -215,10 +211,6 @@ install-exec: $(INSTALL_DIR) -m 755 $(SBINDIR) $(INSTALL_BIN) -m 500 cupsd $(SBINDIR) $(INSTALL_BIN) cupsfilter $(SBINDIR) - -if test "x`uname`" = xDarwin; then \ - $(INSTALL_DIR) $(BUILDROOT)/System/Library/Printers/Libraries; \ - $(LN) $(sbindir)/cupsfilter $(BUILDROOT)/System/Library/Printers/Libraries/convert; \ - fi echo Installing programs in $(SERVERBIN)/daemon... $(INSTALL_DIR) -m 755 $(SERVERBIN) $(INSTALL_DIR) -m 755 $(SERVERBIN)/daemon @@ -438,15 +430,6 @@ cups-lpd: cups-lpd.o ../cups/$(LIBCUPS) $(CC) $(LDFLAGS) -o cups-lpd cups-lpd.o $(LIBS) -# -# Make the polling daemon, "cups-polld". -# - -cups-polld: cups-polld.o ../cups/$(LIBCUPS) - echo Linking $@... - $(CC) $(LDFLAGS) -o cups-polld cups-polld.o $(LIBS) - - # # libcupsmime.so.1, libcupsmime.sl.1 # @@ -506,15 +489,6 @@ libcupsmime.a: $(LIBOBJS) $(RANLIB) $@ -# -# Make the test program, "testdirsvc". -# - -testdirsvc: testdirsvc.o - echo Linking $@... - $(CC) $(LDFLAGS) -o testdirsvc testdirsvc.o $(COMMONLIBS) $(NETLIBS) - - # # Make the test program, "testlpd". # diff --git a/scheduler/cert.c b/scheduler/cert.c index 7de29e707..f1ae1c385 100644 --- a/scheduler/cert.c +++ b/scheduler/cert.c @@ -206,7 +206,7 @@ cupsdAddCert(int pid, /* I - Process ID */ *textptr = ','; cupsdLogMessage(CUPSD_LOG_ERROR, "ACL: %s", text); - free(text); + acl_free(text); } # endif /* HAVE_MBR_UID_TO_UUID */ diff --git a/scheduler/classes.c b/scheduler/classes.c index e1da0aa6a..f5b5bcc62 100644 --- a/scheduler/classes.c +++ b/scheduler/classes.c @@ -1,5 +1,5 @@ /* - * "$Id: classes.c 7724 2008-07-14 06:06:06Z mike $" + * "$Id: classes.c 10104 2011-11-04 06:37:03Z mike $" * * Printer class routines for the CUPS scheduler. * @@ -22,8 +22,6 @@ * cupsdFindClass() - Find the named class. * cupsdLoadAllClasses() - Load classes from the classes.conf file. * cupsdSaveAllClasses() - Save classes to the classes.conf file. - * cupsdUpdateImplicitClasses() - Update the accepting state of implicit - * classes. */ /* @@ -184,24 +182,9 @@ cupsdDeletePrinterFromClasses( for (c = (cupsd_printer_t *)cupsArrayFirst(Printers); c; c = (cupsd_printer_t *)cupsArrayNext(Printers)) - if (c->type & (CUPS_PRINTER_CLASS | CUPS_PRINTER_IMPLICIT)) + if (c->type & CUPS_PRINTER_CLASS) changed |= cupsdDeletePrinterFromClass(c, p); - /* - * Then clean out any empty implicit classes... - */ - - for (c = (cupsd_printer_t *)cupsArrayFirst(ImplicitPrinters); - c; - c = (cupsd_printer_t *)cupsArrayNext(ImplicitPrinters)) - if (c->num_printers == 0) - { - cupsdLogMessage(CUPSD_LOG_DEBUG, "Deleting implicit class \"%s\"...", - c->name); - cupsdDeletePrinter(c, 0); - changed = 1; - } - return (changed); } @@ -279,8 +262,7 @@ cupsdFindClass(const char *name) /* I - Name of class */ cupsd_printer_t *c; /* Current class/printer */ - if ((c = cupsdFindDest(name)) != NULL && - (c->type & (CUPS_PRINTER_CLASS | CUPS_PRINTER_IMPLICIT))) + if ((c = cupsdFindDest(name)) != NULL && (c->type & CUPS_PRINTER_CLASS)) return (c); else return (NULL); @@ -443,9 +425,8 @@ cupsdLoadAllClasses(void) { cupsdSetString(&temp->make_model, "Remote Printer on unknown"); - temp->state = IPP_PRINTER_STOPPED; - temp->type |= CUPS_PRINTER_REMOTE; - temp->browse_time = 2147483647; + temp->state = IPP_PRINTER_STOPPED; + temp->type |= CUPS_PRINTER_REMOTE; cupsdSetString(&temp->location, "Location Unknown"); cupsdSetString(&temp->info, "No Information Available"); @@ -733,7 +714,6 @@ cupsdSaveAllClasses(void) */ if ((pclass->type & CUPS_PRINTER_REMOTE) || - (pclass->type & CUPS_PRINTER_IMPLICIT) || !(pclass->type & CUPS_PRINTER_CLASS)) continue; @@ -834,35 +814,5 @@ cupsdSaveAllClasses(void) /* - * 'cupsdUpdateImplicitClasses()' - Update the accepting state of implicit - * classes. - */ - -void -cupsdUpdateImplicitClasses(void) -{ - int i; /* Looping var */ - cupsd_printer_t *pclass; /* Current class */ - int accepting; /* printer-is-accepting-jobs value */ - - - for (pclass = (cupsd_printer_t *)cupsArrayFirst(ImplicitPrinters); - pclass; - pclass = (cupsd_printer_t *)cupsArrayNext(ImplicitPrinters)) - { - /* - * Loop through the printers to come up with a composite state... - */ - - for (i = 0, accepting = 0; i < pclass->num_printers; i ++) - if ((accepting = pclass->printers[i]->accepting) != 0) - break; - - pclass->accepting = accepting; - } -} - - -/* - * End of "$Id: classes.c 7724 2008-07-14 06:06:06Z mike $". + * End of "$Id: classes.c 10104 2011-11-04 06:37:03Z mike $". */ diff --git a/scheduler/classes.h b/scheduler/classes.h index ef415762a..0170b97e7 100644 --- a/scheduler/classes.h +++ b/scheduler/classes.h @@ -3,7 +3,7 @@ * * Printer class definitions for the CUPS scheduler. * - * Copyright 2007-2010 by Apple Inc. + * Copyright 2007-2011 by Apple Inc. * Copyright 1997-2005 by Easy Software Products, all rights reserved. * * These coded instructions, statements, and computer programs are the @@ -28,7 +28,6 @@ extern cupsd_printer_t *cupsdFindAvailablePrinter(const char *name); extern cupsd_printer_t *cupsdFindClass(const char *name); extern void cupsdLoadAllClasses(void); extern void cupsdSaveAllClasses(void); -extern void cupsdUpdateImplicitClasses(void); /* diff --git a/scheduler/client.c b/scheduler/client.c index c8995916a..2ffdb56c7 100644 --- a/scheduler/client.c +++ b/scheduler/client.c @@ -2842,7 +2842,7 @@ cupsdWriteClient(cupsd_client_t *con) /* I - Client connection */ bytes = ipp_state != IPP_ERROR && (con->file >= 0 || ipp_state != IPP_DATA); } - else if ((bytes = read(con->file, con->header, + else if ((bytes = read(con->file, con->header + con->header_used, sizeof(con->header) - con->header_used)) > 0) { con->header_used += bytes; diff --git a/scheduler/conf.c b/scheduler/conf.c index 2d30822b9..85dce9035 100644 --- a/scheduler/conf.c +++ b/scheduler/conf.c @@ -71,7 +71,7 @@ typedef enum typedef struct { - char *name; /* Name of variable */ + const char *name; /* Name of variable */ void *ptr; /* Pointer to variable */ cupsd_vartype_t type; /* Type (int, string, address) */ } cupsd_var_t; @@ -88,21 +88,6 @@ static const cupsd_var_t variables[] = #ifdef HAVE_DNSSD { "BrowseDNSSDRegType", &DNSSDRegType, CUPSD_VARTYPE_STRING }, #endif /* HAVE_DNSSD */ - { "BrowseInterval", &BrowseInterval, CUPSD_VARTYPE_INTEGER }, -#ifdef HAVE_LDAP - { "BrowseLDAPBindDN", &BrowseLDAPBindDN, CUPSD_VARTYPE_STRING }, -# ifdef HAVE_LDAP_SSL - { "BrowseLDAPCACertFile", &BrowseLDAPCACertFile, CUPSD_VARTYPE_PATHNAME }, -# endif /* HAVE_LDAP_SSL */ - { "BrowseLDAPDN", &BrowseLDAPDN, CUPSD_VARTYPE_STRING }, - { "BrowseLDAPPassword", &BrowseLDAPPassword, CUPSD_VARTYPE_STRING }, - { "BrowseLDAPServer", &BrowseLDAPServer, CUPSD_VARTYPE_STRING }, -#endif /* HAVE_LDAP */ - { "BrowseLocalOptions", &BrowseLocalOptions, CUPSD_VARTYPE_STRING }, - { "BrowsePort", &BrowsePort, CUPSD_VARTYPE_INTEGER }, - { "BrowseRemoteOptions", &BrowseRemoteOptions, CUPSD_VARTYPE_STRING }, - { "BrowseShortNames", &BrowseShortNames, CUPSD_VARTYPE_BOOLEAN }, - { "BrowseTimeout", &BrowseTimeout, CUPSD_VARTYPE_INTEGER }, { "BrowseWebIF", &BrowseWebIF, CUPSD_VARTYPE_BOOLEAN }, { "Browsing", &Browsing, CUPSD_VARTYPE_BOOLEAN }, { "CacheDir", &CacheDir, CUPSD_VARTYPE_STRING }, @@ -123,9 +108,6 @@ static const cupsd_var_t variables[] = { "FilterLimit", &FilterLimit, CUPSD_VARTYPE_INTEGER }, { "FilterNice", &FilterNice, CUPSD_VARTYPE_INTEGER }, { "FontPath", &FontPath, CUPSD_VARTYPE_STRING }, - { "HideImplicitMembers", &HideImplicitMembers, CUPSD_VARTYPE_BOOLEAN }, - { "ImplicitClasses", &ImplicitClasses, CUPSD_VARTYPE_BOOLEAN }, - { "ImplicitAnyClasses", &ImplicitAnyClasses, CUPSD_VARTYPE_BOOLEAN }, { "JobKillDelay", &JobKillDelay, CUPSD_VARTYPE_INTEGER }, { "JobRetryLimit", &JobRetryLimit, CUPSD_VARTYPE_INTEGER }, { "JobRetryInterval", &JobRetryInterval, CUPSD_VARTYPE_INTEGER }, @@ -183,7 +165,6 @@ static const cupsd_var_t variables[] = #endif /* HAVE_AUTHORIZATION_H */ { "TempDir", &TempDir, CUPSD_VARTYPE_PATHNAME }, { "Timeout", &Timeout, CUPSD_VARTYPE_INTEGER }, - { "UseNetworkDefault", &UseNetworkDefault, CUPSD_VARTYPE_BOOLEAN }, { "WebInterface", &WebInterface, CUPSD_VARTYPE_BOOLEAN } }; #define NUM_VARS (sizeof(variables) / sizeof(variables[0])) @@ -451,31 +432,6 @@ cupsdReadConfiguration(void) cupsdDeleteAllLocations(); - if (NumBrowsers > 0) - { - free(Browsers); - Browsers = NULL; - - NumBrowsers = 0; - } - - if (NumPolled > 0) - { - free(Polled); - - NumPolled = 0; - } - - if (NumRelays > 0) - { - for (i = 0; i < NumRelays; i ++) - cupsArrayDelete(Relays[i].from); - - free(Relays); - - NumRelays = 0; - } - cupsdDeleteAllListeners(); old_remote_port = RemotePort; @@ -618,9 +574,6 @@ cupsdReadConfiguration(void) FilterLimit = 0; FilterNice = 0; HostNameLookups = FALSE; - ImplicitClasses = CUPS_DEFAULT_IMPLICIT_CLASSES; - ImplicitAnyClasses = FALSE; - HideImplicitMembers = TRUE; KeepAlive = TRUE; KeepAliveTimeout = DEFAULT_KEEPALIVE; ListenBackLog = SOMAXCONN; @@ -639,12 +592,7 @@ cupsdReadConfiguration(void) NumSystemGroups = 0; WebInterface = CUPS_DEFAULT_WEBIF; - BrowseInterval = DEFAULT_INTERVAL; - BrowsePort = ippPort(); BrowseLocalProtocols = parse_protocols(CUPS_DEFAULT_BROWSE_LOCAL_PROTOCOLS); - BrowseRemoteProtocols = parse_protocols(CUPS_DEFAULT_BROWSE_REMOTE_PROTOCOLS); - BrowseShortNames = CUPS_DEFAULT_BROWSE_SHORT_NAMES; - BrowseTimeout = DEFAULT_TIMEOUT; BrowseWebIF = FALSE; Browsing = CUPS_DEFAULT_BROWSING; DefaultShared = CUPS_DEFAULT_DEFAULT_SHARED; @@ -656,21 +604,8 @@ cupsdReadConfiguration(void) cupsdSetString(&LPDConfigFile, CUPS_DEFAULT_LPD_CONFIG_FILE); cupsdSetString(&SMBConfigFile, CUPS_DEFAULT_SMB_CONFIG_FILE); - cupsdClearString(&BrowseLocalOptions); - cupsdClearString(&BrowseRemoteOptions); - cupsdSetString(&ErrorPolicy, "stop-printer"); -#ifdef HAVE_LDAP - cupsdClearString(&BrowseLDAPBindDN); - cupsdClearString(&BrowseLDAPDN); - cupsdClearString(&BrowseLDAPPassword); - cupsdClearString(&BrowseLDAPServer); -# ifdef HAVE_LDAP_SSL - cupsdClearString(&BrowseLDAPCACertFile); -# endif /* HAVE_LDAP_SSL */ -#endif /* HAVE_LDAP */ - JobHistory = DEFAULT_HISTORY; JobFiles = DEFAULT_FILES; JobAutoPurge = 0; @@ -832,12 +767,6 @@ cupsdReadConfiguration(void) } } - /* - * Get the access control list for browsing... - */ - - BrowseACL = cupsdFindLocation("CUPS_INTERNAL_BROWSE_ACL"); - /* * Open the system log for cupsd if necessary... */ @@ -1150,24 +1079,6 @@ cupsdReadConfiguration(void) "Allowing up to %d client connections per host.", MaxClientsPerHost); - /* - * Make sure that BrowseTimeout is at least twice the interval... - */ - - if (BrowseTimeout < (2 * BrowseInterval) || BrowseTimeout <= 0) - { - cupsdLogMessage(CUPSD_LOG_ALERT, "Invalid BrowseTimeout value %d.", - BrowseTimeout); - - if (BrowseInterval) - BrowseTimeout = BrowseInterval * 2; - else - BrowseTimeout = DEFAULT_TIMEOUT; - - cupsdLogMessage(CUPSD_LOG_ALERT, "Reset BrowseTimeout to %d.", - BrowseTimeout); - } - /* * Update the default policy, as needed... */ @@ -1472,7 +1383,6 @@ cupsdReadConfiguration(void) cupsdLoadAllPrinters(); cupsdLoadAllClasses(); - cupsdLoadRemoteCache(); cupsdCreateCommonData(); @@ -2469,20 +2379,10 @@ parse_protocols(const char *s) /* I - Space-delimited protocols */ * Add the protocol to the bitmask... */ - if (!_cups_strcasecmp(valstart, "cups")) - protocols |= BROWSE_CUPS; - else if (!_cups_strcasecmp(valstart, "slp")) - protocols |= BROWSE_SLP; - else if (!_cups_strcasecmp(valstart, "ldap")) - protocols |= BROWSE_LDAP; - else if (!_cups_strcasecmp(valstart, "dnssd") || - !_cups_strcasecmp(valstart, "dns-sd") || - !_cups_strcasecmp(valstart, "bonjour")) + if (!_cups_strcasecmp(valstart, "dnssd") || + !_cups_strcasecmp(valstart, "dns-sd") || + !_cups_strcasecmp(valstart, "bonjour")) protocols |= BROWSE_DNSSD; - else if (!_cups_strcasecmp(valstart, "lpd")) - protocols |= BROWSE_LPD; - else if (!_cups_strcasecmp(valstart, "smb")) - protocols |= BROWSE_SMB; else if (!_cups_strcasecmp(valstart, "all")) protocols |= BROWSE_ALL; else if (_cups_strcasecmp(valstart, "none")) @@ -2511,18 +2411,12 @@ read_configuration(cups_file_t *fp) /* I - File to read from */ /* Line from file */ temp[HTTP_MAX_BUFFER], /* Temporary buffer for value */ - *ptr, /* Pointer into line/temp */ *value, /* Pointer to value */ *valueptr; /* Pointer into value */ int valuelen; /* Length of value */ cupsd_var_t const *var; /* Current variable */ http_addrlist_t *addrlist, /* Address list */ *addr; /* Current address */ - unsigned ip[4], /* Address value */ - mask[4]; /* Netmask value */ - cupsd_dirsvc_relay_t *relay; /* Relay data */ - cupsd_dirsvc_poll_t *pollp; /* Polling data */ - cupsd_location_t *location; /* Browse location */ cups_file_t *incfile; /* Include file */ char incname[1024]; /* Include filename */ struct group *group; /* Group */ @@ -2706,117 +2600,12 @@ read_configuration(cups_file_t *fp) /* I - File to read from */ httpAddrFreeList(addrlist); } - else if (!_cups_strcasecmp(line, "BrowseAddress") && value) - { - /* - * Add a browse address to the list... - */ - - cupsd_dirsvc_addr_t *dira; /* New browse address array */ - - - if (NumBrowsers == 0) - dira = malloc(sizeof(cupsd_dirsvc_addr_t)); - else - dira = realloc(Browsers, (NumBrowsers + 1) * sizeof(cupsd_dirsvc_addr_t)); - - if (!dira) - { - cupsdLogMessage(CUPSD_LOG_ERROR, - "Unable to allocate BrowseAddress at line %d - %s.", - linenum, strerror(errno)); - continue; - } - - Browsers = dira; - dira += NumBrowsers; - - memset(dira, 0, sizeof(cupsd_dirsvc_addr_t)); - - if (!_cups_strcasecmp(value, "@LOCAL")) - { - /* - * Send browse data to all local interfaces... - */ - - strcpy(dira->iface, "*"); - NumBrowsers ++; - } - else if (!_cups_strncasecmp(value, "@IF(", 4)) - { - /* - * Send browse data to the named interface... - */ - - strlcpy(dira->iface, value + 4, sizeof(Browsers[0].iface)); - - ptr = dira->iface + strlen(dira->iface) - 1; - if (*ptr == ')') - *ptr = '\0'; - - NumBrowsers ++; - } - else if ((addrlist = get_address(value, BrowsePort)) != NULL) - { - /* - * Only IPv4 addresses are supported... - */ - - for (addr = addrlist; addr; addr = addr->next) - if (_httpAddrFamily(&(addr->addr)) == AF_INET) - break; - - if (addr) - { - memcpy(&(dira->to), &(addrlist->addr), sizeof(dira->to)); - httpAddrString(&(dira->to), temp, sizeof(temp)); - - cupsdLogMessage(CUPSD_LOG_INFO, - "Sending browsing info to %s:%d (IPv4)", - temp, _httpAddrPort(&(dira->to))); - - NumBrowsers ++; - } - else - cupsdLogMessage(CUPSD_LOG_ERROR, "Bad BrowseAddress %s at line %d.", - value, linenum); - - httpAddrFreeList(addrlist); - } - else - cupsdLogMessage(CUPSD_LOG_ERROR, "Bad BrowseAddress %s at line %d.", - value, linenum); - } - else if (!_cups_strcasecmp(line, "BrowseOrder") && value) - { - /* - * "BrowseOrder Deny,Allow" or "BrowseOrder Allow,Deny"... - */ - - if ((location = cupsdFindLocation("CUPS_INTERNAL_BROWSE_ACL")) == NULL) - if ((location = cupsdNewLocation("CUPS_INTERNAL_BROWSE_ACL")) != NULL) - cupsdAddLocation(location); - - if (location == NULL) - cupsdLogMessage(CUPSD_LOG_ERROR, - "Unable to initialize browse access control list."); - else if (!_cups_strncasecmp(value, "deny", 4)) - location->order_type = CUPSD_AUTH_ALLOW; - else if (!_cups_strncasecmp(value, "allow", 5)) - location->order_type = CUPSD_AUTH_DENY; - else - cupsdLogMessage(CUPSD_LOG_ERROR, - "Unknown BrowseOrder value %s on line %d.", - value, linenum); - } else if (!_cups_strcasecmp(line, "BrowseProtocols") || - !_cups_strcasecmp(line, "BrowseLocalProtocols") || - !_cups_strcasecmp(line, "BrowseRemoteProtocols")) + !_cups_strcasecmp(line, "BrowseLocalProtocols")) { /* * "BrowseProtocols name [... name]" * "BrowseLocalProtocols name [... name]" - * "BrowseRemoteProtocols name [... name]" */ int protocols = parse_protocols(value); @@ -2829,367 +2618,7 @@ read_configuration(cups_file_t *fp) /* I - File to read from */ break; } - if (_cups_strcasecmp(line, "BrowseLocalProtocols")) - BrowseRemoteProtocols = protocols; - if (_cups_strcasecmp(line, "BrowseRemoteProtocols")) - BrowseLocalProtocols = protocols; - } - else if ((!_cups_strcasecmp(line, "BrowseAllow") || - !_cups_strcasecmp(line, "BrowseDeny")) && value) - { - /* - * BrowseAllow [From] host/ip... - * BrowseDeny [From] host/ip... - */ - - if ((location = cupsdFindLocation("CUPS_INTERNAL_BROWSE_ACL")) == NULL) - if ((location = cupsdNewLocation("CUPS_INTERNAL_BROWSE_ACL")) != NULL) - cupsdAddLocation(location); - - - if (location == NULL) - cupsdLogMessage(CUPSD_LOG_ERROR, - "Unable to initialize browse access control list."); - else - { - if (!_cups_strncasecmp(value, "from", 4)) - { - /* - * Skip leading "from"... - */ - - value += 4; - } - - while (*value) - { - /* - * Skip leading whitespace... - */ - - while (_cups_isspace(*value)) - value ++; - - if (!*value) - break; - - /* - * Find the end of the value... - */ - - for (valueptr = value; - *valueptr && !_cups_isspace(*valueptr); - valueptr ++); - - while (_cups_isspace(*valueptr)) - *valueptr++ = '\0'; - - /* - * Figure out what form the allow/deny address takes: - * - * All - * None - * *.domain.com - * .domain.com - * host.domain.com - * nnn.* - * nnn.nnn.* - * nnn.nnn.nnn.* - * nnn.nnn.nnn.nnn - * nnn.nnn.nnn.nnn/mm - * nnn.nnn.nnn.nnn/mmm.mmm.mmm.mmm - */ - - if (!_cups_strcasecmp(value, "all")) - { - /* - * All hosts... - */ - - if (!_cups_strcasecmp(line, "BrowseAllow")) - cupsdAddIPMask(&(location->allow), zeros, zeros); - else - cupsdAddIPMask(&(location->deny), zeros, zeros); - } - else if (!_cups_strcasecmp(value, "none")) - { - /* - * No hosts... - */ - - if (!_cups_strcasecmp(line, "BrowseAllow")) - cupsdAddIPMask(&(location->allow), ones, zeros); - else - cupsdAddIPMask(&(location->deny), ones, zeros); - } -#ifdef AF_INET6 - else if (value[0] == '*' || value[0] == '.' || - (!isdigit(value[0] & 255) && value[0] != '[')) -#else - else if (value[0] == '*' || value[0] == '.' || - !isdigit(value[0] & 255)) -#endif /* AF_INET6 */ - { - /* - * Host or domain name... - */ - - if (!_cups_strcasecmp(line, "BrowseAllow")) - cupsdAddNameMask(&(location->allow), value); - else - cupsdAddNameMask(&(location->deny), value); - } - else - { - /* - * One of many IP address forms... - */ - - if (!get_addr_and_mask(value, ip, mask)) - { - cupsdLogMessage(CUPSD_LOG_ERROR, "Bad netmask value %s on line %d.", - value, linenum); - break; - } - - if (!_cups_strcasecmp(line, "BrowseAllow")) - cupsdAddIPMask(&(location->allow), ip, mask); - else - cupsdAddIPMask(&(location->deny), ip, mask); - } - - /* - * Advance to next value... - */ - - value = valueptr; - } - } - } - else if (!_cups_strcasecmp(line, "BrowseRelay") && value) - { - /* - * BrowseRelay [from] source [to] destination - */ - - if (NumRelays == 0) - relay = malloc(sizeof(cupsd_dirsvc_relay_t)); - else - relay = realloc(Relays, (NumRelays + 1) * sizeof(cupsd_dirsvc_relay_t)); - - if (!relay) - { - cupsdLogMessage(CUPSD_LOG_ERROR, - "Unable to allocate BrowseRelay at line %d - %s.", - linenum, strerror(errno)); - continue; - } - - Relays = relay; - relay += NumRelays; - - memset(relay, 0, sizeof(cupsd_dirsvc_relay_t)); - - if (!_cups_strncasecmp(value, "from ", 5)) - { - /* - * Skip leading "from"... - */ - - value += 5; - - /* - * Skip leading whitespace... - */ - - while (_cups_isspace(*value)) - value ++; - } - - /* - * Find the end of the from value... - */ - - for (valueptr = value; - *valueptr && !_cups_isspace(*valueptr); - valueptr ++); - - while (_cups_isspace(*valueptr)) - *valueptr++ = '\0'; - - /* - * Figure out what form the from address takes: - * - * *.domain.com - * .domain.com - * host.domain.com - * nnn.* - * nnn.nnn.* - * nnn.nnn.nnn.* - * nnn.nnn.nnn.nnn - * nnn.nnn.nnn.nnn/mm - * nnn.nnn.nnn.nnn/mmm.mmm.mmm.mmm - */ - -#ifdef AF_INET6 - if (value[0] == '*' || value[0] == '.' || - (!isdigit(value[0] & 255) && value[0] != '[')) -#else - if (value[0] == '*' || value[0] == '.' || !isdigit(value[0] & 255)) -#endif /* AF_INET6 */ - { - /* - * Host or domain name... - */ - - if (!cupsdAddNameMask(&(relay->from), value)) - { - cupsdLogMessage(CUPSD_LOG_ERROR, - "Unable to allocate BrowseRelay name at line %d - %s.", - linenum, strerror(errno)); - continue; - } - } - else - { - /* - * One of many IP address forms... - */ - - if (!get_addr_and_mask(value, ip, mask)) - { - cupsdLogMessage(CUPSD_LOG_ERROR, "Bad netmask value %s on line %d.", - value, linenum); - break; - } - - if (!cupsdAddIPMask(&(relay->from), ip, mask)) - { - cupsdLogMessage(CUPSD_LOG_ERROR, - "Unable to allocate BrowseRelay IP at line %d - %s.", - linenum, strerror(errno)); - continue; - } - } - - /* - * Get "to" address and port... - */ - - if (!_cups_strncasecmp(valueptr, "to ", 3)) - { - /* - * Strip leading "to"... - */ - - valueptr += 3; - - while (_cups_isspace(*valueptr)) - valueptr ++; - } - - if ((addrlist = get_address(valueptr, BrowsePort)) != NULL) - { - /* - * Only IPv4 addresses are supported... - */ - - for (addr = addrlist; addr; addr = addr->next) - if (addr->addr.addr.sa_family == AF_INET) - break; - - if (addr) - { - memcpy(&(relay->to), &(addrlist->addr), sizeof(relay->to)); - - httpAddrString(&(relay->to), temp, sizeof(temp)); - - cupsdLogMessage(CUPSD_LOG_INFO, "Relaying from %s to %s:%d (IPv4)", - value, temp, _httpAddrPort(&(relay->to))); - - NumRelays ++; - } - else - { - cupsArrayDelete(relay->from); - relay->from = NULL; - - cupsdLogMessage(CUPSD_LOG_ERROR, "Bad relay address %s at line %d.", - valueptr, linenum); - } - - httpAddrFreeList(addrlist); - } - else - { - cupsArrayDelete(relay->from); - relay->from = NULL; - - cupsdLogMessage(CUPSD_LOG_ERROR, "Bad relay address %s at line %d.", - valueptr, linenum); - } - } - else if (!_cups_strcasecmp(line, "BrowsePoll") && value) - { - /* - * BrowsePoll address[:port] - */ - - char *portname; /* Port name */ - int portnum; /* Port number */ - struct servent *service; /* Service */ - - - /* - * Extract the port name from the address... - */ - - if ((portname = strrchr(value, ':')) != NULL && !strchr(portname, ']')) - { - *portname++ = '\0'; - - if (isdigit(*portname & 255)) - portnum = atoi(portname); - else if ((service = getservbyname(portname, NULL)) != NULL) - portnum = ntohs(service->s_port); - else - { - cupsdLogMessage(CUPSD_LOG_ERROR, "Lookup of service \"%s\" failed.", - portname); - continue; - } - } - else - portnum = ippPort(); - - /* - * Add the poll entry... - */ - - if (NumPolled == 0) - pollp = malloc(sizeof(cupsd_dirsvc_poll_t)); - else - pollp = realloc(Polled, (NumPolled + 1) * sizeof(cupsd_dirsvc_poll_t)); - - if (!pollp) - { - cupsdLogMessage(CUPSD_LOG_ERROR, - "Unable to allocate BrowsePoll at line %d - %s.", - linenum, strerror(errno)); - continue; - } - - Polled = pollp; - pollp += NumPolled; - - NumPolled ++; - memset(pollp, 0, sizeof(cupsd_dirsvc_poll_t)); - - strlcpy(pollp->hostname, value, sizeof(pollp->hostname)); - pollp->port = portnum; - - cupsdLogMessage(CUPSD_LOG_INFO, "Polling %s:%d", pollp->hostname, - pollp->port); + BrowseLocalProtocols = protocols; } else if (!_cups_strcasecmp(line, "DefaultAuthType") && value) { diff --git a/scheduler/conf.h b/scheduler/conf.h index a68c31d3b..4a0b5961e 100644 --- a/scheduler/conf.h +++ b/scheduler/conf.h @@ -193,12 +193,6 @@ VAR int MaxClients VALUE(100), /* Support the Keep-Alive option? */ KeepAliveTimeout VALUE(DEFAULT_KEEPALIVE), /* Timeout between requests */ - ImplicitClasses VALUE(TRUE), - /* Are classes implicitly created? */ - ImplicitAnyClasses VALUE(FALSE), - /* Create AnyPrinter classes? */ - HideImplicitMembers VALUE(TRUE), - /* Hide implicit class members? */ FileDevice VALUE(FALSE), /* Allow file: devices? */ FilterLimit VALUE(0), diff --git a/scheduler/cups-driverd.cxx b/scheduler/cups-driverd.cxx index 714871c85..2fa741e91 100644 --- a/scheduler/cups-driverd.cxx +++ b/scheduler/cups-driverd.cxx @@ -1774,7 +1774,8 @@ load_ppds(const char *d, /* I - Actual directory */ product[256], /* Product */ psversion[256], /* PSVersion */ temp[512]; /* Temporary make and model */ - int model_number, /* cupsModelNumber */ + int install_group, /* In the installable options group? */ + model_number, /* cupsModelNumber */ type; /* ppd-type */ cups_array_t *products, /* Product array */ *psversions, /* PSVersion array */ @@ -1998,6 +1999,7 @@ load_ppds(const char *d, /* I - Actual directory */ lang_encoding[0] = '\0'; strcpy(lang_version, "en"); model_number = 0; + install_group = 0; type = PPD_TYPE_POSTSCRIPT; while (cupsFileGets(fp, line, sizeof(line)) != NULL) @@ -2092,15 +2094,19 @@ load_ppds(const char *d, /* I - Actual directory */ } else if (!strncmp(line, "*cupsModelNumber:", 17)) sscanf(line, "*cupsModelNumber:%d", &model_number); + else if (!strncmp(line, "*OpenGroup: Installable", 23)) + install_group = 1; + else if (!strncmp(line, "*CloseGroup:", 12)) + install_group = 0; else if (!strncmp(line, "*OpenUI", 7)) { /* * Stop early if we have a NickName or ModelName attributes - * before the first OpenUI... + * before the first non-installable OpenUI... */ - if ((model_name[0] || nick_name[0]) && cupsArrayCount(products) > 0 && - cupsArrayCount(psversions) > 0) + if (!install_group && (model_name[0] || nick_name[0]) && + cupsArrayCount(products) > 0 && cupsArrayCount(psversions) > 0) break; } } diff --git a/scheduler/cups-polld.c b/scheduler/cups-polld.c deleted file mode 100644 index 35ac250b7..000000000 --- a/scheduler/cups-polld.c +++ /dev/null @@ -1,469 +0,0 @@ -/* - * "$Id: cups-polld.c 7198 2008-01-08 00:12:17Z mike $" - * - * Polling daemon for CUPS. - * - * Copyright 2007-2011 by Apple Inc. - * Copyright 1997-2006 by Easy Software Products, all rights reserved. - * - * These coded instructions, statements, and computer programs are the - * property of Apple Inc. and are protected by Federal copyright - * law. Distribution and use rights are outlined in the file "LICENSE.txt" - * which should have been included with this file. If this file is - * file is missing or damaged, see the license at "http://www.cups.org/". - * - * Contents: - * - * main() - Open sockets and poll until we are killed... - * dequote() - Remote quotes from a string. - * poll_server() - Poll the server for the given set of printers or - * classes. - * sighup_handler() - Handle 'hangup' signals to restart polling. - */ - -/* - * Include necessary headers... - */ - -#include -#include - - -/* - * Local globals... - */ - -static int restart_polling = 1; - - -/* - * Local functions... - */ - -static char *dequote(char *d, const char *s, int dlen); -static int poll_server(http_t *http, int sock, int port, int interval, - const char *prefix); -static void sighup_handler(int sig); - - -/* - * 'main()' - Open sockets and poll until we are killed... - */ - -int /* O - Exit status */ -main(int argc, /* I - Number of command-line args */ - char *argv[]) /* I - Command-line arguments */ -{ - http_t *http; /* HTTP connection */ - int interval; /* Polling interval */ - int sock; /* Browser sock */ - int port; /* Browser port */ - int val; /* Socket option value */ - int seconds, /* Seconds left from poll */ - remain; /* Total remaining time to sleep */ - char prefix[1024]; /* Prefix for log messages */ -#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET) - struct sigaction action; /* Actions for POSIX signals */ -#endif /* HAVE_SIGACTION && !HAVE_SIGSET */ - - - /* - * Catch hangup signals for when the network changes... - */ - -#ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */ - sigset(SIGHUP, sighup_handler); -#elif defined(HAVE_SIGACTION) - memset(&action, 0, sizeof(action)); - - sigemptyset(&action.sa_mask); - sigaddset(&action.sa_mask, SIGHUP); - action.sa_handler = sighup_handler; - sigaction(SIGHUP, &action, NULL); -#else - signal(SIGHUP, sighup_handler); -#endif /* HAVE_SIGSET */ - - /* - * Don't buffer log messages... - */ - - setbuf(stderr, NULL); - - /* - * The command-line must contain the following: - * - * cups-polld server server-port interval port - */ - - if (argc != 5) - { - fputs("Usage: cups-polld server server-port interval port\n", stderr); - return (1); - } - - interval = atoi(argv[3]); - port = atoi(argv[4]); - - if (interval < 2) - interval = 2; - - snprintf(prefix, sizeof(prefix), "[cups-polld %s:%d]", argv[1], atoi(argv[2])); - - /* - * Open a broadcast socket... - */ - - if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) - { - fprintf(stderr, "ERROR: %s Unable to open broadcast socket: %s\n", prefix, - strerror(errno)); - return (1); - } - - /* - * Set the "broadcast" flag... - */ - - val = 1; - if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &val, sizeof(val))) - { - fprintf(stderr, "ERROR: %s Unable to put socket in broadcast mode: %s\n", - prefix, strerror(errno)); - - close(sock); - return (1); - } - - /* - * Loop forever, asking for available printers and classes... - */ - - for (http = NULL; !ferror(stderr);) - { - /* - * Open a connection to the server... - */ - - if (restart_polling || !http) - { - restart_polling = 0; - httpClose(http); - - if ((http = httpConnectEncrypt(argv[1], atoi(argv[2]), - cupsEncryption())) == NULL) - { - fprintf(stderr, "ERROR: %s Unable to connect to %s on port %s.\n", - prefix, argv[1], argv[2]); - } - } - - /* - * Get the printers and classes... - */ - - remain = interval; - - if (http && (seconds = poll_server(http, sock, port, interval, prefix)) > 0) - remain -= seconds; - - /* - * Sleep for any remaining time... - */ - - if (remain > 0 && !restart_polling) - sleep(remain); - } - - return (1); -} - - -/* - * 'dequote()' - Remote quotes from a string. - */ - -static char * /* O - Dequoted string */ -dequote(char *d, /* I - Destination string */ - const char *s, /* I - Source string */ - int dlen) /* I - Destination length */ -{ - char *dptr; /* Pointer into destination */ - - - if (s) - { - for (dptr = d, dlen --; *s && dlen > 0; s ++) - if (*s != '\"') - { - *dptr++ = *s; - dlen --; - } - - *dptr = '\0'; - } - else - *d = '\0'; - - return (d); -} - - -/* - * 'poll_server()' - Poll the server for the given set of printers or classes. - */ - -static int /* O - Number of seconds or -1 on error */ -poll_server(http_t *http, /* I - HTTP connection */ - int sock, /* I - Broadcast sock */ - int port, /* I - Broadcast port */ - int interval, /* I - Polling interval */ - const char *prefix) /* I - Prefix for log messages */ -{ - int seconds; /* Number of seconds */ - int count, /* Current number of printers/classes */ - max_count; /* Maximum printers/classes per second */ - ipp_t *request, /* Request data */ - *response; /* Response data */ - ipp_attribute_t *attr; /* Current attribute */ - const char *uri; /* printer-uri */ - char info[1024], /* printer-info */ - job_sheets[1024],/* job-sheets-default */ - location[1024], /* printer-location */ - make_model[1024]; - /* printer-make-and-model */ - cups_ptype_t type; /* printer-type */ - ipp_pstate_t state; /* printer-state */ - int accepting; /* printer-is-accepting-jobs */ - struct sockaddr_in addr; /* Broadcast address */ - char packet[1540]; /* Data packet */ - static const char * const attrs[] = /* Requested attributes */ - { - "job-sheets-default", - "printer-info", - "printer-is-accepting-jobs", - "printer-location", - "printer-make-and-model", - "printer-name", - "printer-state", - "printer-type", - "printer-uri-supported" - }; - - - /* - * Broadcast to 127.0.0.1 (localhost) - */ - - memset(&addr, 0, sizeof(addr)); - addr.sin_addr.s_addr = htonl(0x7f000001); - addr.sin_family = AF_INET; - addr.sin_port = htons(port); - - /* - * Build a CUPS_GET_PRINTERS request and pass along a list of the - * attributes we are interested in along with the types of printers - * (and classes) we want. - */ - - request = ippNewRequest(CUPS_GET_PRINTERS); - - ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, - "requested-attributes", sizeof(attrs) / sizeof(attrs[0]), - NULL, attrs); - - ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_ENUM, - "printer-type", 0); - ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_ENUM, - "printer-type-mask", - CUPS_PRINTER_REMOTE | CUPS_PRINTER_IMPLICIT | - CUPS_PRINTER_NOT_SHARED); - - /* - * Do the request and get back a response... - */ - - seconds = time(NULL); - response = cupsDoRequest(http, request, "/"); - - if (cupsLastError() > IPP_OK_CONFLICT) - { - fprintf(stderr, "ERROR: %s CUPS-Get-Printers failed: %s\n", prefix, - cupsLastErrorString()); - ippDelete(response); - return (-1); - } - - if (response) - { - /* - * Figure out how many printers/classes we have... - */ - - for (attr = ippFindAttribute(response, "printer-name", IPP_TAG_NAME), - max_count = 0; - attr != NULL; - attr = ippFindNextAttribute(response, "printer-name", IPP_TAG_NAME), - max_count ++); - - fprintf(stderr, "DEBUG: %s Found %d printers.\n", prefix, max_count); - - count = 0; - max_count = 2 * max_count / interval + 1; - - /* - * Loop through the printers or classes returned in the list... - */ - - for (attr = response->attrs; attr; attr = attr->next) - { - /* - * Skip leading attributes until we hit a printer... - */ - - while (attr && attr->group_tag != IPP_TAG_PRINTER) - attr = attr->next; - - if (!attr) - break; - - /* - * Pull the needed attributes from this printer... - */ - - uri = NULL; - info[0] = '\0'; - job_sheets[0] = '\0'; - location[0] = '\0'; - make_model[0] = '\0'; - type = CUPS_PRINTER_REMOTE; - accepting = 1; - state = IPP_PRINTER_IDLE; - - while (attr != NULL && attr->group_tag == IPP_TAG_PRINTER) - { - if (!strcmp(attr->name, "job-sheets-default") && - (attr->value_tag == IPP_TAG_NAME || - attr->value_tag == IPP_TAG_KEYWORD)) - { - if (attr->num_values == 1) - snprintf(job_sheets, sizeof(job_sheets), " job-sheets=%s", - attr->values[0].string.text); - else - snprintf(job_sheets, sizeof(job_sheets), " job-sheets=%s,%s", - attr->values[0].string.text, - attr->values[1].string.text); - } - else if (!strcmp(attr->name, "printer-uri-supported") && - attr->value_tag == IPP_TAG_URI) - uri = attr->values[0].string.text; - else if (!strcmp(attr->name, "printer-info") && - attr->value_tag == IPP_TAG_TEXT) - dequote(info, attr->values[0].string.text, sizeof(info)); - else if (!strcmp(attr->name, "printer-is-accepting-jobs") && - attr->value_tag == IPP_TAG_BOOLEAN) - accepting = attr->values[0].boolean; - else if (!strcmp(attr->name, "printer-location") && - attr->value_tag == IPP_TAG_TEXT) - dequote(location, attr->values[0].string.text, sizeof(location)); - else if (!strcmp(attr->name, "printer-make-and-model") && - attr->value_tag == IPP_TAG_TEXT) - dequote(make_model, attr->values[0].string.text, sizeof(location)); - else if (!strcmp(attr->name, "printer-state") && - attr->value_tag == IPP_TAG_ENUM) - state = (ipp_pstate_t)attr->values[0].integer; - else if (!strcmp(attr->name, "printer-type") && - attr->value_tag == IPP_TAG_ENUM) - type = (cups_ptype_t)attr->values[0].integer; - - attr = attr->next; - } - - /* - * See if we have everything needed... - */ - - if (uri == NULL) - { - if (attr == NULL) - break; - else - continue; - } - - /* - * Send the printer information... - */ - - type |= CUPS_PRINTER_REMOTE; - - if (!accepting) - type |= CUPS_PRINTER_REJECTING; - - snprintf(packet, sizeof(packet), - "%x %x %s \"%s\" \"%s\" \"%s\" lease-duration=%d%s\n", - type, state, uri, location, info, make_model, interval * 2, - job_sheets); - - fprintf(stderr, "DEBUG2: %s Sending %s", prefix, packet); - - if (sendto(sock, packet, strlen(packet), 0, - (struct sockaddr *)&addr, sizeof(addr)) <= 0) - { - ippDelete(response); - perror("cups-polld"); - return (-1); - } - - /* - * Throttle the local broadcasts as needed so that we don't - * overwhelm the local server... - */ - - count ++; - if (count >= max_count) - { - /* - * Sleep for a second... - */ - - count = 0; - - sleep(1); - } - - if (!attr || restart_polling) - break; - } - - ippDelete(response); - } - - /* - * Return the number of seconds we used... - */ - - return (time(NULL) - seconds); -} - - -/* - * 'sighup_handler()' - Handle 'hangup' signals to restart polling. - */ - -static void -sighup_handler(int sig) /* I - Signal number */ -{ - (void)sig; - - restart_polling = 1; - -#if !defined(HAVE_SIGSET) && !defined(HAVE_SIGACTION) - signal(SIGHUP, sighup_handler); -#endif /* !HAVE_SIGSET && !HAVE_SIGACTION */ -} - - -/* - * End of "$Id: cups-polld.c 7198 2008-01-08 00:12:17Z mike $". - */ diff --git a/scheduler/dirsvc.c b/scheduler/dirsvc.c index eb8fd2264..05cdb7a10 100644 --- a/scheduler/dirsvc.c +++ b/scheduler/dirsvc.c @@ -14,68 +14,31 @@ * * Contents: * - * cupsdDeregisterPrinter() - Stop sending broadcast information for a local - * printer and remove any pending references to - * remote printers. - * cupsdLoadRemoteCache() - Load the remote printer cache. - * cupsdRegisterPrinter() - Start sending broadcast information for a - * printer or update the broadcast contents. - * cupsdRestartPolling() - Restart polling servers as needed. - * cupsdSaveRemoteCache() - Save the remote printer cache. - * cupsdSendBrowseList() - Send new browsing information as necessary. - * ldap_rebind_proc() - Callback function for LDAP rebind - * ldap_connect() - Start new LDAP connection - * ldap_reconnect() - Reconnect to LDAP Server - * ldap_disconnect() - Disconnect from LDAP Server - * cupsdStartBrowsing() - Start sending and receiving broadcast - * information. - * cupsdStartPolling() - Start polling servers as needed. - * cupsdStopBrowsing() - Stop sending and receiving broadcast - * information. - * cupsdStopPolling() - Stop polling servers as needed. - * cupsdUpdateDNSSDName() - Update the computer name we use for - * browsing... - * cupsdUpdateLDAPBrowse() - Scan for new printers via LDAP... - * cupsdUpdateSLPBrowse() - Get browsing information via SLP. - * dequote() - Remote quotes from a string. - * dnssdAddAlias() - Add a DNS-SD alias name. - * dnssdBuildTxtRecord() - Build a TXT record from printer info. - * dnssdComparePrinters() - Compare the registered names of two printers. - * dnssdDeregisterPrinter() - Stop sending broadcast information for a - * printer. - * dnssdPackTxtRecord() - Pack an array of key/value pairs into the TXT - * record format. - * dnssdRegisterCallback() - DNSServiceRegister callback. - * dnssdRegisterPrinter() - Start sending broadcast information for a - * printer or update the broadcast contents. - * dnssdStop() - Stop all DNS-SD registrations. - * dnssdUpdate() - Handle DNS-SD queries. - * get_auth_info_required() - Get the auth-info-required value to advertise. - * get_hostconfig() - Get an /etc/hostconfig service setting. - * is_local_queue() - Determine whether the URI points at a local - * queue. - * process_browse_data() - Process new browse data. - * process_implicit_classes() - Create/update implicit classes as needed. - * send_cups_browse() - Send new browsing information using the CUPS - * protocol. - * ldap_search_rec() - LDAP Search with reconnect - * ldap_freeres() - Free LDAPMessage - * ldap_getval_char() - Get first LDAP value and convert to string - * send_ldap_ou() - Send LDAP ou registrations. - * send_ldap_browse() - Send LDAP printer registrations. - * ldap_dereg_printer() - Delete printer from directory - * ldap_dereg_ou() - Remove the organizational unit. - * send_slp_browse() - Register the specified printer with SLP. - * slp_attr_callback() - SLP attribute callback - * slp_dereg_printer() - SLPDereg() the specified printer - * slp_get_attr() - Get an attribute from an SLP registration. - * slp_reg_callback() - Empty SLPRegReport. - * slp_url_callback() - SLP service url callback - * update_cups_browse() - Update the browse lists using the CUPS - * protocol. - * update_lpd() - Update the LPD configuration as needed. - * update_polling() - Read status messages from the poll daemons. - * update_smb() - Update the SMB configuration as needed. + * cupsdDeregisterPrinter() - Stop sending broadcast information for a local + * printer and remove any pending references to + * remote printers. + * cupsdRegisterPrinter() - Start sending broadcast information for a + * printer or update the broadcast contents. + * cupsdStartBrowsing() - Start sending and receiving broadcast + * information. + * cupsdStopBrowsing() - Stop sending and receiving broadcast + * information. + * cupsdUpdateDNSSDName() - Update the computer name we use for browsing... + * dnssdAddAlias() - Add a DNS-SD alias name. + * dnssdBuildTxtRecord() - Build a TXT record from printer info. + * dnssdDeregisterPrinter() - Stop sending broadcast information for a + * printer. + * dnssdPackTxtRecord() - Pack an array of key/value pairs into the TXT + * record format. + * dnssdRegisterCallback() - DNSServiceRegister callback. + * dnssdRegisterPrinter() - Start sending broadcast information for a + * printer or update the broadcast contents. + * dnssdStop() - Stop all DNS-SD registrations. + * dnssdUpdate() - Handle DNS-SD queries. + * get_auth_info_required() - Get the auth-info-required value to advertise. + * get_hostconfig() - Get an /etc/hostconfig service setting. + * update_lpd() - Update the LPD configuration as needed. + * update_smb() - Update the SMB configuration as needed. */ /* @@ -103,59 +66,12 @@ * Local functions... */ -static char *dequote(char *d, const char *s, int dlen); static char *get_auth_info_required(cupsd_printer_t *p, char *buffer, size_t bufsize); #ifdef __APPLE__ static int get_hostconfig(const char *name); #endif /* __APPLE__ */ -static int is_local_queue(const char *uri, char *host, int hostlen, - char *resource, int resourcelen); -static void process_browse_data(const char *uri, const char *host, - const char *resource, cups_ptype_t type, - ipp_pstate_t state, const char *location, - const char *info, const char *make_model, - int num_attrs, cups_option_t *attrs); -static void process_implicit_classes(void); -static void send_cups_browse(cupsd_printer_t *p); -#ifdef HAVE_LDAP -static LDAP *ldap_connect(void); -static LDAP *ldap_reconnect(void); -static void ldap_disconnect(LDAP *ld); -static int ldap_search_rec(LDAP *ld, char *base, int scope, - char *filter, char *attrs[], - int attrsonly, LDAPMessage **res); -static int ldap_getval_firststring(LDAP *ld, LDAPMessage *entry, - char *attr, char *retval, - unsigned long maxsize); -static void ldap_freeres(LDAPMessage *entry); -static void send_ldap_ou(char *ou, char *basedn, char *descstring); -static void send_ldap_browse(cupsd_printer_t *p); -static void ldap_dereg_printer(cupsd_printer_t *p); -static void ldap_dereg_ou(char *ou, char *basedn); -# ifdef HAVE_LDAP_REBIND_PROC -# if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000) -static int ldap_rebind_proc(LDAP *RebindLDAPHandle, - LDAP_CONST char *refsp, - ber_tag_t request, - ber_int_t msgid, - void *params); -# else -static int ldap_rebind_proc(LDAP *RebindLDAPHandle, - char **dnp, - char **passwdp, - int *authmethodp, - int freeit, - void *arg); -# endif /* defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000) */ -# endif /* HAVE_LDAP_REBIND_PROC */ -#endif /* HAVE_LDAP */ -#ifdef HAVE_LIBSLP -static void send_slp_browse(cupsd_printer_t *p); -#endif /* HAVE_LIBSLP */ -static void update_cups_browse(void); static void update_lpd(int onoff); -static void update_polling(void); static void update_smb(int onoff); @@ -166,7 +82,6 @@ static void dnssdAddAlias(const void *key, const void *value, # endif /* HAVE_COREFOUNDATION */ static char *dnssdBuildTxtRecord(int *txt_len, cupsd_printer_t *p, int for_lpd); -static int dnssdComparePrinters(cupsd_printer_t *a, cupsd_printer_t *b); static void dnssdDeregisterPrinter(cupsd_printer_t *p); static char *dnssdPackTxtRecord(int *txt_len, char *keyvalue[][2], int count); @@ -180,59 +95,6 @@ static void dnssdStop(void); static void dnssdUpdate(void); #endif /* HAVE_DNSSD */ -#ifdef HAVE_LDAP -static const char * const ldap_attrs[] =/* CUPS LDAP attributes */ - { - "printerDescription", - "printerLocation", - "printerMakeAndModel", - "printerType", - "printerURI", - NULL - }; -#endif /* HAVE_LDAP */ - -#ifdef HAVE_LIBSLP -/* - * SLP definitions... - */ - -/* - * SLP service name for CUPS... - */ - -# define SLP_CUPS_SRVTYPE "service:printer" -# define SLP_CUPS_SRVLEN 15 - - -/* - * Printer service URL structure - */ - -typedef struct _slpsrvurl_s /**** SLP URL list ****/ -{ - struct _slpsrvurl_s *next; /* Next URL in list */ - char url[HTTP_MAX_URI]; - /* URL */ -} slpsrvurl_t; - - -/* - * Local functions... - */ - -static SLPBoolean slp_attr_callback(SLPHandle hslp, const char *attrlist, - SLPError errcode, void *cookie); -static void slp_dereg_printer(cupsd_printer_t *p); -static int slp_get_attr(const char *attrlist, const char *tag, - char **valbuf); -static void slp_reg_callback(SLPHandle hslp, SLPError errcode, - void *cookie); -static SLPBoolean slp_url_callback(SLPHandle hslp, const char *srvurl, - unsigned short lifetime, - SLPError errcode, void *cookie); -#endif /* HAVE_LIBSLP */ - /* * 'cupsdDeregisterPrinter()' - Stop sending broadcast information for a @@ -254,5125 +116,1104 @@ cupsdDeregisterPrinter( removeit); if (!Browsing || !p->shared || - (p->type & (CUPS_PRINTER_REMOTE | CUPS_PRINTER_IMPLICIT | - CUPS_PRINTER_SCANNER))) + (p->type & (CUPS_PRINTER_REMOTE | CUPS_PRINTER_SCANNER))) return; /* * Announce the deletion... */ - if ((BrowseLocalProtocols & BROWSE_CUPS) && BrowseSocket >= 0) - { - cups_ptype_t savedtype = p->type; /* Saved printer type */ - - p->type |= CUPS_PRINTER_DELETE; +#ifdef HAVE_DNSSD + if (removeit && (BrowseLocalProtocols & BROWSE_DNSSD) && DNSSDRef) + dnssdDeregisterPrinter(p); +#endif /* HAVE_DNSSD */ +} - send_cups_browse(p); - p->type = savedtype; - } +/* + * 'cupsdRegisterPrinter()' - Start sending broadcast information for a + * printer or update the broadcast contents. + */ -#ifdef HAVE_LIBSLP - if (BrowseLocalProtocols & BROWSE_SLP) - slp_dereg_printer(p); -#endif /* HAVE_LIBSLP */ +void +cupsdRegisterPrinter(cupsd_printer_t *p)/* I - Printer */ +{ + cupsdLogMessage(CUPSD_LOG_DEBUG, "cupsdRegisterPrinter(p=%p(%s))", p, + p->name); -#ifdef HAVE_LDAP - if (BrowseLocalProtocols & BROWSE_LDAP) - ldap_dereg_printer(p); -#endif /* HAVE_LDAP */ + if (!Browsing || !BrowseLocalProtocols || + (p->type & (CUPS_PRINTER_REMOTE | CUPS_PRINTER_SCANNER))) + return; #ifdef HAVE_DNSSD - if (removeit && (BrowseLocalProtocols & BROWSE_DNSSD) && DNSSDRef) - dnssdDeregisterPrinter(p); + if ((BrowseLocalProtocols & BROWSE_DNSSD) && DNSSDRef) + dnssdRegisterPrinter(p); #endif /* HAVE_DNSSD */ } /* - * 'cupsdLoadRemoteCache()' - Load the remote printer cache. + * 'cupsdStartBrowsing()' - Start sending and receiving broadcast information. */ void -cupsdLoadRemoteCache(void) +cupsdStartBrowsing(void) { - int i; /* Looping var */ - cups_file_t *fp; /* remote.cache file */ - int linenum; /* Current line number */ - char line[4096], /* Line from file */ - *value, /* Pointer to value */ - *valueptr, /* Pointer into value */ - scheme[32], /* Scheme portion of URI */ - username[64], /* Username portion of URI */ - host[HTTP_MAX_HOST], - /* Hostname portion of URI */ - resource[HTTP_MAX_URI]; - /* Resource portion of URI */ - int port; /* Port number */ cupsd_printer_t *p; /* Current printer */ - time_t now; /* Current time */ - - - /* - * Don't load the cache if the remote protocols are disabled... - */ - if (!Browsing) - { - cupsdLogMessage(CUPSD_LOG_DEBUG, - "cupsdLoadRemoteCache: Not loading remote cache."); - return; - } - /* - * Open the remote.cache file... - */ - - snprintf(line, sizeof(line), "%s/remote.cache", CacheDir); - if ((fp = cupsdOpenConfFile(line)) == NULL) + if (!Browsing || !BrowseLocalProtocols) return; - /* - * Read printer configurations until we hit EOF... - */ +#ifdef HAVE_DNSSD + if (BrowseLocalProtocols & BROWSE_DNSSD) + { + DNSServiceErrorType error; /* Error from service creation */ + cupsd_listener_t *lis; /* Current listening socket */ - linenum = 0; - p = NULL; - now = time(NULL); - while (cupsFileGetConf(fp, line, sizeof(line), &value, &linenum)) - { /* - * Decode the directive... + * First create a "master" connection for all registrations... */ - if (!_cups_strcasecmp(line, " or - */ - - if (p == NULL && value) - { - /* - * Add the printer and a base file type... - */ - - cupsdLogMessage(CUPSD_LOG_DEBUG, - "cupsdLoadRemoteCache: Loading printer %s...", value); - - if ((p = cupsdFindDest(value)) != NULL) - { - if (p->type & CUPS_PRINTER_CLASS) - { - cupsdLogMessage(CUPSD_LOG_WARN, - "Cached remote printer \"%s\" conflicts with " - "existing class!", - value); - p = NULL; - continue; - } - } - else - p = cupsdAddPrinter(value); - - p->accepting = 1; - p->state = IPP_PRINTER_IDLE; - p->type |= CUPS_PRINTER_REMOTE | CUPS_PRINTER_DISCOVERED; - p->browse_time = now; - p->browse_expire = now + BrowseTimeout; - - /* - * Set the default printer as needed... - */ - - if (!_cups_strcasecmp(line, " or - */ - - if (p == NULL && value) - { - /* - * Add the printer and a base file type... - */ - - cupsdLogMessage(CUPSD_LOG_DEBUG, - "cupsdLoadRemoteCache: Loading class %s...", value); - - if ((p = cupsdFindDest(value)) != NULL) - p->type = CUPS_PRINTER_CLASS; - else - p = cupsdAddClass(value); - - p->accepting = 1; - p->state = IPP_PRINTER_IDLE; - p->type |= CUPS_PRINTER_REMOTE | CUPS_PRINTER_DISCOVERED; - p->browse_time = now; - p->browse_expire = now + BrowseTimeout; - - /* - * Set the default printer as needed... - */ - - if (!_cups_strcasecmp(line, "") || - !_cups_strcasecmp(line, "")) - { - if (p != NULL) - { - /* - * Close out the current printer... - */ - - cupsdSetPrinterAttrs(p); - - p = NULL; - } - else - cupsdLogMessage(CUPSD_LOG_ERROR, - "Syntax error on line %d of remote.cache.", linenum); - } - else if (!p) + if ((error = DNSServiceCreateConnection(&DNSSDRef)) + != kDNSServiceErr_NoError) { cupsdLogMessage(CUPSD_LOG_ERROR, - "Syntax error on line %d of remote.cache.", linenum); - } - else if (!_cups_strcasecmp(line, "UUID")) - { - if (value && !strncmp(value, "urn:uuid:", 9)) - cupsdSetString(&(p->uuid), value); - else - cupsdLogMessage(CUPSD_LOG_ERROR, - "Bad UUID on line %d of remote.cache.", linenum); - } - else if (!_cups_strcasecmp(line, "Info")) - { - if (value) - cupsdSetString(&p->info, value); - } - else if (!_cups_strcasecmp(line, "MakeModel")) - { - if (value) - cupsdSetString(&p->make_model, value); - } - else if (!_cups_strcasecmp(line, "Location")) - { - if (value) - cupsdSetString(&p->location, value); - } - else if (!_cups_strcasecmp(line, "DeviceURI")) - { - if (value) - { - httpSeparateURI(HTTP_URI_CODING_ALL, value, scheme, sizeof(scheme), - username, sizeof(username), host, sizeof(host), &port, - resource, sizeof(resource)); + "Unable to create master DNS-SD reference: %d", error); - cupsdSetString(&p->hostname, host); - cupsdSetString(&p->uri, value); - cupsdSetDeviceURI(p, value); - } - else - cupsdLogMessage(CUPSD_LOG_ERROR, - "Syntax error on line %d of remote.cache.", linenum); + if (FatalErrors & CUPSD_FATAL_BROWSE) + cupsdEndProcess(getpid(), 0); } - else if (!_cups_strcasecmp(line, "Option") && value) + else { /* - * Option name value + * Add the master connection to the select list... */ - for (valueptr = value; *valueptr && !isspace(*valueptr & 255); valueptr ++); + int fd = DNSServiceRefSockFD(DNSSDRef); - if (!*valueptr) - cupsdLogMessage(CUPSD_LOG_ERROR, - "Syntax error on line %d of remote.cache.", linenum); - else - { - for (; *valueptr && isspace(*valueptr & 255); *valueptr++ = '\0'); + fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC); - p->num_options = cupsAddOption(value, valueptr, p->num_options, - &(p->options)); - } - } - else if (!_cups_strcasecmp(line, "Reason")) - { - if (value) - { - for (i = 0 ; i < p->num_reasons; i ++) - if (!strcmp(value, p->reasons[i])) - break; - - if (i >= p->num_reasons && - p->num_reasons < (int)(sizeof(p->reasons) / sizeof(p->reasons[0]))) - { - p->reasons[p->num_reasons] = _cupsStrAlloc(value); - p->num_reasons ++; - } - } - else - cupsdLogMessage(CUPSD_LOG_ERROR, - "Syntax error on line %d of remote.cache.", linenum); - } - else if (!_cups_strcasecmp(line, "State")) - { - /* - * Set the initial queue state... - */ + cupsdAddSelect(fd, (cupsd_selfunc_t)dnssdUpdate, NULL, NULL); - if (value && !_cups_strcasecmp(value, "idle")) - p->state = IPP_PRINTER_IDLE; - else if (value && !_cups_strcasecmp(value, "stopped")) - { - p->state = IPP_PRINTER_STOPPED; - cupsdSetPrinterReasons(p, "+paused"); - } - else - cupsdLogMessage(CUPSD_LOG_ERROR, - "Syntax error on line %d of remote.cache.", linenum); - } - else if (!_cups_strcasecmp(line, "StateMessage")) - { /* - * Set the initial queue state message... + * Then get the port we use for registrations. If we are not listening + * on any non-local ports, there is no sense sharing local printers via + * Bonjour... */ - if (value) - strlcpy(p->state_message, value, sizeof(p->state_message)); - } - else if (!_cups_strcasecmp(line, "Accepting")) - { - /* - * Set the initial accepting state... - */ + DNSSDPort = 0; - if (value && - (!_cups_strcasecmp(value, "yes") || - !_cups_strcasecmp(value, "on") || - !_cups_strcasecmp(value, "true"))) - p->accepting = 1; - else if (value && - (!_cups_strcasecmp(value, "no") || - !_cups_strcasecmp(value, "off") || - !_cups_strcasecmp(value, "false"))) - p->accepting = 0; - else - cupsdLogMessage(CUPSD_LOG_ERROR, - "Syntax error on line %d of remote.cache.", linenum); - } - else if (!_cups_strcasecmp(line, "Type")) - { - if (value) - p->type = atoi(value); - else - cupsdLogMessage(CUPSD_LOG_ERROR, - "Syntax error on line %d of remote.cache.", linenum); - } - else if (!_cups_strcasecmp(line, "BrowseTime")) - { - if (value) + for (lis = (cupsd_listener_t *)cupsArrayFirst(Listeners); + lis; + lis = (cupsd_listener_t *)cupsArrayNext(Listeners)) { - time_t t = atoi(value); + if (httpAddrLocalhost(&(lis->address))) + continue; - if (t > p->browse_expire) - p->browse_expire = t; + DNSSDPort = _httpAddrPort(&(lis->address)); + break; } - else - cupsdLogMessage(CUPSD_LOG_ERROR, - "Syntax error on line %d of remote.cache.", linenum); - } - else if (!_cups_strcasecmp(line, "JobSheets")) - { - /* - * Set the initial job sheets... - */ - if (value) - { - for (valueptr = value; *valueptr && !isspace(*valueptr & 255); valueptr ++); - - if (*valueptr) - *valueptr++ = '\0'; - - cupsdSetString(&p->job_sheets[0], value); - - while (isspace(*valueptr & 255)) - valueptr ++; - - if (*valueptr) - { - for (value = valueptr; *valueptr && !isspace(*valueptr & 255); valueptr ++); - - if (*valueptr) - *valueptr = '\0'; - - cupsdSetString(&p->job_sheets[1], value); - } - } - else - cupsdLogMessage(CUPSD_LOG_ERROR, - "Syntax error on line %d of remote.cache.", linenum); - } - else if (!_cups_strcasecmp(line, "AllowUser")) - { - if (value) - { - p->deny_users = 0; - cupsdAddString(&(p->users), value); - } - else - cupsdLogMessage(CUPSD_LOG_ERROR, - "Syntax error on line %d of remote.cache.", linenum); - } - else if (!_cups_strcasecmp(line, "DenyUser")) - { - if (value) - { - p->deny_users = 1; - cupsdAddString(&(p->users), value); - } - else - cupsdLogMessage(CUPSD_LOG_ERROR, - "Syntax error on line %d of remote.cache.", linenum); - } - else - { /* - * Something else we don't understand... + * Set the computer name and register the web interface... */ - cupsdLogMessage(CUPSD_LOG_ERROR, - "Unknown configuration directive %s on line %d of remote.cache.", - line, linenum); + cupsdUpdateDNSSDName(); } } +#endif /* HAVE_DNSSD */ + + /* + * Enable LPD and SMB printer sharing as needed through external programs... + */ + + if (BrowseLocalProtocols & BROWSE_LPD) + update_lpd(1); - cupsFileClose(fp); + if (BrowseLocalProtocols & BROWSE_SMB) + update_smb(1); /* - * Do auto-classing if needed... + * Register the individual printers */ - process_implicit_classes(); + for (p = (cupsd_printer_t *)cupsArrayFirst(Printers); + p; + p = (cupsd_printer_t *)cupsArrayNext(Printers)) + if (!(p->type & (CUPS_PRINTER_REMOTE | CUPS_PRINTER_SCANNER))) + cupsdRegisterPrinter(p); } /* - * 'cupsdRegisterPrinter()' - Start sending broadcast information for a - * printer or update the broadcast contents. + * 'cupsdStopBrowsing()' - Stop sending and receiving broadcast information. */ void -cupsdRegisterPrinter(cupsd_printer_t *p)/* I - Printer */ +cupsdStopBrowsing(void) { - cupsdLogMessage(CUPSD_LOG_DEBUG, "cupsdRegisterPrinter(p=%p(%s))", p, - p->name); + cupsd_printer_t *p; /* Current printer */ - if (!Browsing || !BrowseLocalProtocols || - (p->type & (CUPS_PRINTER_REMOTE | CUPS_PRINTER_IMPLICIT | - CUPS_PRINTER_SCANNER))) + + if (!Browsing || !BrowseLocalProtocols) return; -#ifdef HAVE_LIBSLP -/* if (BrowseLocalProtocols & BROWSE_SLP) - slpRegisterPrinter(p); */ -#endif /* HAVE_LIBSLP */ + /* + * De-register the individual printers + */ + + for (p = (cupsd_printer_t *)cupsArrayFirst(Printers); + p; + p = (cupsd_printer_t *)cupsArrayNext(Printers)) + if (!(p->type & (CUPS_PRINTER_REMOTE | CUPS_PRINTER_SCANNER))) + cupsdDeregisterPrinter(p, 1); + + /* + * Shut down browsing sockets... + */ #ifdef HAVE_DNSSD if ((BrowseLocalProtocols & BROWSE_DNSSD) && DNSSDRef) - dnssdRegisterPrinter(p); + dnssdStop(); #endif /* HAVE_DNSSD */ -} - - -/* - * 'cupsdRestartPolling()' - Restart polling servers as needed. - */ -void -cupsdRestartPolling(void) -{ - int i; /* Looping var */ - cupsd_dirsvc_poll_t *pollp; /* Current polling server */ + /* + * Disable LPD and SMB printer sharing as needed through external programs... + */ + if (BrowseLocalProtocols & BROWSE_LPD) + update_lpd(0); - for (i = 0, pollp = Polled; i < NumPolled; i ++, pollp ++) - if (pollp->pid) - kill(pollp->pid, SIGHUP); + if (BrowseLocalProtocols & BROWSE_SMB) + update_smb(0); } +#ifdef HAVE_DNSSD /* - * 'cupsdSaveRemoteCache()' - Save the remote printer cache. + * 'cupsdUpdateDNSSDName()' - Update the computer name we use for browsing... */ void -cupsdSaveRemoteCache(void) +cupsdUpdateDNSSDName(void) { - int i; /* Looping var */ - cups_file_t *fp; /* remote.cache file */ - char filename[1024], /* remote.cache filename */ - temp[1024], /* Temporary string */ - value[2048], /* Value string */ - *name; /* Current user name */ - cupsd_printer_t *printer; /* Current printer class */ - time_t curtime; /* Current time */ - struct tm *curdate; /* Current date */ - cups_option_t *option; /* Current option */ + DNSServiceErrorType error; /* Error from service creation */ + char webif[1024]; /* Web interface share name */ +# ifdef HAVE_SYSTEMCONFIGURATION + SCDynamicStoreRef sc; /* Context for dynamic store */ + CFDictionaryRef btmm; /* Back-to-My-Mac domains */ + CFStringEncoding nameEncoding; /* Encoding of computer name */ + CFStringRef nameRef; /* Host name CFString */ + char nameBuffer[1024]; /* C-string buffer */ +# endif /* HAVE_SYSTEMCONFIGURATION */ /* - * Create the remote.cache file... - */ - - snprintf(filename, sizeof(filename), "%s/remote.cache", CacheDir); + * Only share the web interface and printers when non-local listening is + * enabled... + */ - if ((fp = cupsdCreateConfFile(filename, ConfigFilePerm)) == NULL) + if (!DNSSDPort) return; - cupsdLogMessage(CUPSD_LOG_DEBUG, "Saving remote.cache..."); - /* - * Write a small header to the file... + * Get the computer name as a c-string... */ - curtime = time(NULL); - curdate = localtime(&curtime); - strftime(temp, sizeof(temp) - 1, "%Y-%m-%d %H:%M", curdate); - - cupsFilePuts(fp, "# Remote cache file for " CUPS_SVERSION "\n"); - cupsFilePrintf(fp, "# Written by cupsd on %s\n", temp); - - /* - * Write each local printer known to the system... - */ +# ifdef HAVE_SYSTEMCONFIGURATION + sc = SCDynamicStoreCreate(kCFAllocatorDefault, CFSTR("cupsd"), NULL, NULL); - for (printer = (cupsd_printer_t *)cupsArrayFirst(Printers); - printer; - printer = (cupsd_printer_t *)cupsArrayNext(Printers)) + if (sc) { /* - * Skip local destinations... - */ - - if (!(printer->type & CUPS_PRINTER_DISCOVERED)) - continue; - - /* - * Write printers as needed... + * Get the computer name from the dynamic store... */ - if (printer == DefaultPrinter) - cupsFilePuts(fp, "type & CUPS_PRINTER_CLASS) - cupsFilePrintf(fp, "Class %s>\n", printer->name); - else - cupsFilePrintf(fp, "Printer %s>\n", printer->name); - - cupsFilePrintf(fp, "BrowseTime %d\n", (int)printer->browse_expire); - - cupsFilePrintf(fp, "UUID %s\n", printer->uuid); - - if (printer->info) - cupsFilePutConf(fp, "Info", printer->info); - - if (printer->location) - cupsFilePutConf(fp, "Location", printer->location); - - if (printer->make_model) - cupsFilePutConf(fp, "MakeModel", printer->make_model); - - cupsFilePutConf(fp, "DeviceURI", printer->device_uri); - - if (printer->state == IPP_PRINTER_STOPPED) - cupsFilePuts(fp, "State Stopped\n"); - else - cupsFilePuts(fp, "State Idle\n"); - - for (i = 0; i < printer->num_reasons; i ++) - cupsFilePutConf(fp, "Reason", printer->reasons[i]); - - cupsFilePrintf(fp, "Type %d\n", printer->type); - - if (printer->accepting) - cupsFilePuts(fp, "Accepting Yes\n"); - else - cupsFilePuts(fp, "Accepting No\n"); - - snprintf(value, sizeof(value), "%s %s", printer->job_sheets[0], - printer->job_sheets[1]); - cupsFilePutConf(fp, "JobSheets", value); - - for (name = (char *)cupsArrayFirst(printer->users); - name; - name = (char *)cupsArrayNext(printer->users)) - cupsFilePutConf(fp, printer->deny_users ? "DenyUser" : "AllowUser", name); + cupsdClearString(&DNSSDComputerName); - for (i = printer->num_options, option = printer->options; - i > 0; - i --, option ++) + if ((nameRef = SCDynamicStoreCopyComputerName(sc, &nameEncoding)) != NULL) { - snprintf(value, sizeof(value), "%s %s", option->name, option->value); - cupsFilePutConf(fp, "Option", value); - } - - if (printer->type & CUPS_PRINTER_CLASS) - cupsFilePuts(fp, "\n"); - else - cupsFilePuts(fp, "\n"); - } - - cupsdCloseCreatedConfFile(fp, filename); -} - - -/* - * 'cupsdSendBrowseList()' - Send new browsing information as necessary. - */ - -void -cupsdSendBrowseList(void) -{ - int count; /* Number of dests to update */ - cupsd_printer_t *p; /* Current printer */ - time_t ut, /* Minimum update time */ - to; /* Timeout time */ - - - if (!Browsing || !Printers) - return; - - /* - * Compute the update and timeout times... - */ - - to = time(NULL); - ut = to - BrowseInterval; + if (CFStringGetCString(nameRef, nameBuffer, sizeof(nameBuffer), + kCFStringEncodingUTF8)) + { + cupsdLogMessage(CUPSD_LOG_DEBUG, + "Dynamic store computer name is \"%s\".", nameBuffer); + cupsdSetString(&DNSSDComputerName, nameBuffer); + } - /* - * Figure out how many printers need an update... - */ + CFRelease(nameRef); + } - if (BrowseInterval > 0 && BrowseLocalProtocols) - { - int max_count; /* Maximum number to update */ + if (!DNSSDComputerName) + { + /* + * Use the ServerName instead... + */ + cupsdLogMessage(CUPSD_LOG_DEBUG, + "Using ServerName \"%s\" as computer name.", ServerName); + cupsdSetString(&DNSSDComputerName, ServerName); + } /* - * Throttle the number of printers we'll be updating this time - * around based on the number of queues that need updating and - * the maximum number of queues to update each second... + * Get the local hostname from the dynamic store... */ - max_count = 2 * cupsArrayCount(Printers) / BrowseInterval + 1; - - for (count = 0, p = (cupsd_printer_t *)cupsArrayFirst(Printers); - count < max_count && p != NULL; - p = (cupsd_printer_t *)cupsArrayNext(Printers)) - if (!(p->type & (CUPS_PRINTER_REMOTE | CUPS_PRINTER_IMPLICIT | - CUPS_PRINTER_SCANNER)) && - p->shared && p->browse_time < ut) - count ++; + cupsdClearString(&DNSSDHostName); - /* - * Loop through all of the printers and send local updates as needed... - */ + if ((nameRef = SCDynamicStoreCopyLocalHostName(sc)) != NULL) + { + if (CFStringGetCString(nameRef, nameBuffer, sizeof(nameBuffer), + kCFStringEncodingUTF8)) + { + cupsdLogMessage(CUPSD_LOG_DEBUG, + "Dynamic store host name is \"%s\".", nameBuffer); + cupsdSetString(&DNSSDHostName, nameBuffer); + } - if (BrowseNext) - p = (cupsd_printer_t *)cupsArrayFind(Printers, BrowseNext); - else - p = (cupsd_printer_t *)cupsArrayFirst(Printers); + CFRelease(nameRef); + } - for (; - count > 0; - p = (cupsd_printer_t *)cupsArrayNext(Printers)) + if (!DNSSDHostName) { /* - * Check for wraparound... + * Use the ServerName instead... */ - if (!p) - p = (cupsd_printer_t *)cupsArrayFirst(Printers); - - if (!p) - break; - else if ((p->type & (CUPS_PRINTER_REMOTE | CUPS_PRINTER_IMPLICIT | - CUPS_PRINTER_SCANNER)) || - !p->shared) - continue; - else if (p->browse_time < ut) - { - /* - * Need to send an update... - */ - - count --; - - p->browse_time = time(NULL); - - if ((BrowseLocalProtocols & BROWSE_CUPS) && BrowseSocket >= 0) - send_cups_browse(p); - -#ifdef HAVE_LIBSLP - if (BrowseLocalProtocols & BROWSE_SLP) - send_slp_browse(p); -#endif /* HAVE_LIBSLP */ - -#ifdef HAVE_LDAP - if (BrowseLocalProtocols & BROWSE_LDAP) - send_ldap_browse(p); -#endif /* HAVE_LDAP */ - } + cupsdLogMessage(CUPSD_LOG_DEBUG, + "Using ServerName \"%s\" as host name.", ServerName); + cupsdSetString(&DNSSDHostName, ServerName); } /* - * Save where we left off so that all printers get updated... + * Get any Back-to-My-Mac domains and add them as aliases... */ - BrowseNext = p; - } - - /* - * Loop through all of the printers and timeout old printers as needed... - */ - - for (p = (cupsd_printer_t *)cupsArrayFirst(Printers); - p; - p = (cupsd_printer_t *)cupsArrayNext(Printers)) - { - /* - * If this is a remote queue, see if it needs to be timed out... - */ + cupsdFreeAliases(DNSSDAlias); + DNSSDAlias = NULL; - if ((p->type & CUPS_PRINTER_DISCOVERED) && - !(p->type & CUPS_PRINTER_IMPLICIT) && - p->browse_expire < to) + btmm = SCDynamicStoreCopyValue(sc, CFSTR("Setup:/Network/BackToMyMac")); + if (btmm && CFGetTypeID(btmm) == CFDictionaryGetTypeID()) { - cupsdAddEvent(CUPSD_EVENT_PRINTER_DELETED, p, NULL, - "%s \'%s\' deleted by directory services (timeout).", - (p->type & CUPS_PRINTER_CLASS) ? "Class" : "Printer", - p->name); - - cupsdLogMessage(CUPSD_LOG_DEBUG, - "Remote destination \"%s\" has timed out; " - "deleting it...", - p->name); - - cupsArraySave(Printers); - cupsdDeletePrinter(p, 1); - cupsArrayRestore(Printers); - cupsdMarkDirty(CUPSD_DIRTY_PRINTCAP | CUPSD_DIRTY_REMOTE); + cupsdLogMessage(CUPSD_LOG_DEBUG, "%d Back to My Mac aliases to add.", + (int)CFDictionaryGetCount(btmm)); + CFDictionaryApplyFunction(btmm, dnssdAddAlias, NULL); } - } -} - - -#ifdef HAVE_LDAP_REBIND_PROC -# if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000) -/* - * 'ldap_rebind_proc()' - Callback function for LDAP rebind - */ - -static int /* O - Result code */ -ldap_rebind_proc( - LDAP *RebindLDAPHandle, /* I - LDAP handle */ - LDAP_CONST char *refsp, /* I - ??? */ - ber_tag_t request, /* I - ??? */ - ber_int_t msgid, /* I - ??? */ - void *params) /* I - ??? */ -{ - int rc; /* Result code */ -# if LDAP_API_VERSION > 3000 - struct berval bval; /* Bind value */ -# endif /* LDAP_API_VERSION > 3000 */ + else if (btmm) + cupsdLogMessage(CUPSD_LOG_ERROR, + "Bad Back to My Mac data in dynamic store!"); + else + cupsdLogMessage(CUPSD_LOG_DEBUG, "No Back to My Mac aliases to add."); + if (btmm) + CFRelease(btmm); - (void)request; - (void)msgid; - (void)params; + CFRelease(sc); + } + else +# endif /* HAVE_SYSTEMCONFIGURATION */ + { + cupsdSetString(&DNSSDComputerName, ServerName); + cupsdSetString(&DNSSDHostName, ServerName); + } /* - * Bind to new LDAP server... + * Then (re)register the web interface if enabled... */ - cupsdLogMessage(CUPSD_LOG_DEBUG2, "ldap_rebind_proc: Rebind to %s", refsp); - -# if LDAP_API_VERSION > 3000 - bval.bv_val = BrowseLDAPPassword; - bval.bv_len = (BrowseLDAPPassword == NULL) ? 0 : strlen(BrowseLDAPPassword); + if (BrowseWebIF) + { + if (DNSSDComputerName) + snprintf(webif, sizeof(webif), "CUPS @ %s", DNSSDComputerName); + else + strlcpy(webif, "CUPS Web Interface", sizeof(webif)); - rc = ldap_sasl_bind_s(RebindLDAPHandle, BrowseLDAPBindDN, LDAP_SASL_SIMPLE, - &bval, NULL, NULL, NULL); -# else - rc = ldap_bind_s(RebindLDAPHandle, BrowseLDAPBindDN, BrowseLDAPPassword, - LDAP_AUTH_SIMPLE); -# endif /* LDAP_API_VERSION > 3000 */ + if (WebIFRef) + DNSServiceRefDeallocate(WebIFRef); - return (rc); + WebIFRef = DNSSDRef; + if ((error = DNSServiceRegister(&WebIFRef, + kDNSServiceFlagsShareConnection, + 0, webif, "_http._tcp", NULL, + NULL, htons(DNSSDPort), 7, + "\006path=/", dnssdRegisterCallback, + NULL)) != kDNSServiceErr_NoError) + cupsdLogMessage(CUPSD_LOG_ERROR, + "DNS-SD web interface registration failed: %d", error); + } } +#endif /* HAVE_DNSSD */ -# else /* defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000) */ +#ifdef HAVE_DNSSD +# ifdef HAVE_COREFOUNDATION /* - * 'ldap_rebind_proc()' - Callback function for LDAP rebind + * 'dnssdAddAlias()' - Add a DNS-SD alias name. */ -static int /* O - Result code */ -ldap_rebind_proc( - LDAP *RebindLDAPHandle, /* I - LDAP handle */ - char **dnp, /* I - ??? */ - char **passwdp, /* I - ??? */ - int *authmethodp, /* I - ??? */ - int freeit, /* I - ??? */ - void *arg) /* I - ??? */ +static void +dnssdAddAlias(const void *key, /* I - Key */ + const void *value, /* I - Value (domain) */ + void *context) /* I - Unused */ { - switch (freeit) - { - case 1: - /* - * Free current values... - */ - - cupsdLogMessage(CUPSD_LOG_DEBUG2, "ldap_rebind_proc: Free values..."); - - if (dnp && *dnp) - free(*dnp); - - if (passwdp && *passwdp) - free(*passwdp); - break; - - case 0: - /* - * Return credentials for LDAP referal... - */ + char valueStr[1024], /* Domain string */ + hostname[1024]; /* Complete hostname */ - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "ldap_rebind_proc: Return necessary values..."); - *dnp = strdup(BrowseLDAPBindDN); - *passwdp = strdup(BrowseLDAPPassword); - *authmethodp = LDAP_AUTH_SIMPLE; - break; + (void)key; + (void)context; - default: - /* - * Should never happen... - */ + if (CFGetTypeID((CFStringRef)value) == CFStringGetTypeID() && + CFStringGetCString((CFStringRef)value, valueStr, sizeof(valueStr), + kCFStringEncodingUTF8)) + { + snprintf(hostname, sizeof(hostname), "%s.%s", DNSSDHostName, valueStr); + if (!DNSSDAlias) + DNSSDAlias = cupsArrayNew(NULL, NULL); - cupsdLogMessage(CUPSD_LOG_ERROR, - "LDAP rebind has been called with wrong freeit value!"); - break; + cupsdAddAlias(DNSSDAlias, hostname); + cupsdLogMessage(CUPSD_LOG_DEBUG, "Added Back to My Mac ServerAlias %s", + hostname); } - - return (LDAP_SUCCESS); + else + cupsdLogMessage(CUPSD_LOG_ERROR, + "Bad Back to My Mac domain in dynamic store!"); } -# endif /* defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000) */ -#endif /* HAVE_LDAP_REBIND_PROC */ +# endif /* HAVE_COREFOUNDATION */ -#ifdef HAVE_LDAP /* - * 'ldap_connect()' - Start new LDAP connection + * 'dnssdBuildTxtRecord()' - Build a TXT record from printer info. */ -static LDAP * /* O - LDAP handle */ -ldap_connect(void) -{ - int rc; /* LDAP API status */ - int version = 3; /* LDAP version */ - struct berval bv = {0, ""}; /* SASL bind value */ - LDAP *TempBrowseLDAPHandle=NULL; - /* Temporary LDAP Handle */ -# if defined(HAVE_LDAP_SSL) && defined (HAVE_MOZILLA_LDAP) - int ldap_ssl = 0; /* LDAP SSL indicator */ - int ssl_err = 0; /* LDAP SSL error value */ -# endif /* defined(HAVE_LDAP_SSL) && defined (HAVE_MOZILLA_LDAP) */ - - -# ifdef HAVE_OPENLDAP -# ifdef HAVE_LDAP_SSL - /* - * Set the certificate file to use for encrypted LDAP sessions... - */ - - if (BrowseLDAPCACertFile) - { - cupsdLogMessage(CUPSD_LOG_DEBUG, - "ldap_connect: Setting CA certificate file \"%s\"", - BrowseLDAPCACertFile); - - if ((rc = ldap_set_option(NULL, LDAP_OPT_X_TLS_CACERTFILE, - (void *)BrowseLDAPCACertFile)) != LDAP_SUCCESS) - cupsdLogMessage(CUPSD_LOG_ERROR, - "Unable to set CA certificate file for LDAP " - "connections: %d - %s", rc, ldap_err2string(rc)); - } -# endif /* HAVE_LDAP_SSL */ - - /* - * Initialize OPENLDAP connection... - * LDAP stuff currently only supports ldapi EXTERNAL SASL binds... - */ - - if (!BrowseLDAPServer || !_cups_strcasecmp(BrowseLDAPServer, "localhost")) - rc = ldap_initialize(&TempBrowseLDAPHandle, "ldapi:///"); - else - rc = ldap_initialize(&TempBrowseLDAPHandle, BrowseLDAPServer); - -# else /* HAVE_OPENLDAP */ - - int ldap_port = 0; /* LDAP port */ - char ldap_protocol[11], /* LDAP protocol */ - ldap_host[255]; /* LDAP host */ - - /* - * Split LDAP URI into its components... - */ - - if (!BrowseLDAPServer) - { - cupsdLogMessage(CUPSD_LOG_ERROR, "BrowseLDAPServer not configured!"); - cupsdLogMessage(CUPSD_LOG_ERROR, "Disabling LDAP browsing!"); - BrowseLocalProtocols &= ~BROWSE_LDAP; - BrowseRemoteProtocols &= ~BROWSE_LDAP; - return (NULL); - } - - sscanf(BrowseLDAPServer, "%10[^:]://%254[^:/]:%d", ldap_protocol, ldap_host, - &ldap_port); - - if (!strcmp(ldap_protocol, "ldap")) - ldap_ssl = 0; - else if (!strcmp(ldap_protocol, "ldaps")) - ldap_ssl = 1; - else - { - cupsdLogMessage(CUPSD_LOG_ERROR, "Unrecognized LDAP protocol (%s)!", - ldap_protocol); - cupsdLogMessage(CUPSD_LOG_ERROR, "Disabling LDAP browsing!"); - BrowseLocalProtocols &= ~BROWSE_LDAP; - BrowseRemoteProtocols &= ~BROWSE_LDAP; - return (NULL); - } - - if (ldap_port == 0) - { - if (ldap_ssl) - ldap_port = LDAPS_PORT; - else - ldap_port = LDAP_PORT; - } - - cupsdLogMessage(CUPSD_LOG_DEBUG, "ldap_connect: PROT:%s HOST:%s PORT:%d", - ldap_protocol, ldap_host, ldap_port); - - /* - * Initialize LDAP connection... - */ - - if (!ldap_ssl) - { - if ((TempBrowseLDAPHandle = ldap_init(ldap_host, ldap_port)) == NULL) - rc = LDAP_OPERATIONS_ERROR; - else - rc = LDAP_SUCCESS; - -# ifdef HAVE_LDAP_SSL - } - else - { - /* - * Initialize SSL LDAP connection... - */ - - if (BrowseLDAPCACertFile) - { - rc = ldapssl_client_init(BrowseLDAPCACertFile, (void *)NULL); - if (rc != LDAP_SUCCESS) - { - cupsdLogMessage(CUPSD_LOG_ERROR, - "Failed to initialize LDAP SSL client!"); - rc = LDAP_OPERATIONS_ERROR; - } - else - { - if ((TempBrowseLDAPHandle = ldapssl_init(ldap_host, ldap_port, - 1)) == NULL) - rc = LDAP_OPERATIONS_ERROR; - else - rc = LDAP_SUCCESS; - } - } - else - { - cupsdLogMessage(CUPSD_LOG_ERROR, - "LDAP SSL certificate file/database not configured!"); - rc = LDAP_OPERATIONS_ERROR; - } - -# else /* HAVE_LDAP_SSL */ - - /* - * Return error, because client libraries doesn't support SSL - */ - - cupsdLogMessage(CUPSD_LOG_ERROR, - "LDAP client libraries do not support SSL"); - rc = LDAP_OPERATIONS_ERROR; - -# endif /* HAVE_LDAP_SSL */ - } -# endif /* HAVE_OPENLDAP */ - - /* - * Check return code from LDAP initialize... - */ - - if (rc != LDAP_SUCCESS) - { - cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to initialize LDAP!"); - - if (rc == LDAP_SERVER_DOWN || rc == LDAP_CONNECT_ERROR) - cupsdLogMessage(CUPSD_LOG_ERROR, "Temporarily disabling LDAP browsing..."); - else - { - cupsdLogMessage(CUPSD_LOG_ERROR, "Disabling LDAP browsing!"); - - BrowseLocalProtocols &= ~BROWSE_LDAP; - BrowseRemoteProtocols &= ~BROWSE_LDAP; - } - - ldap_disconnect(TempBrowseLDAPHandle); - - return (NULL); - } - - /* - * Upgrade LDAP version... - */ - - if (ldap_set_option(TempBrowseLDAPHandle, LDAP_OPT_PROTOCOL_VERSION, - (const void *)&version) != LDAP_SUCCESS) - { - cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to set LDAP protocol version %d!", - version); - cupsdLogMessage(CUPSD_LOG_ERROR, "Disabling LDAP browsing!"); - - BrowseLocalProtocols &= ~BROWSE_LDAP; - BrowseRemoteProtocols &= ~BROWSE_LDAP; - ldap_disconnect(TempBrowseLDAPHandle); - - return (NULL); - } - - /* - * Register LDAP rebind procedure... - */ - -# ifdef HAVE_LDAP_REBIND_PROC -# if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000) - - rc = ldap_set_rebind_proc(TempBrowseLDAPHandle, &ldap_rebind_proc, - (void *)NULL); - if (rc != LDAP_SUCCESS) - cupsdLogMessage(CUPSD_LOG_ERROR, - "Setting LDAP rebind function failed with status %d: %s", - rc, ldap_err2string(rc)); - -# else - - ldap_set_rebind_proc(TempBrowseLDAPHandle, &ldap_rebind_proc, (void *)NULL); - -# endif /* defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000) */ -# endif /* HAVE_LDAP_REBIND_PROC */ - - /* - * Start LDAP bind... - */ - -# if LDAP_API_VERSION > 3000 - struct berval bval; - bval.bv_val = BrowseLDAPPassword; - bval.bv_len = (BrowseLDAPPassword == NULL) ? 0 : strlen(BrowseLDAPPassword); - - if (!BrowseLDAPServer || !_cups_strcasecmp(BrowseLDAPServer, "localhost")) - rc = ldap_sasl_bind_s(TempBrowseLDAPHandle, NULL, "EXTERNAL", &bv, NULL, - NULL, NULL); - else - rc = ldap_sasl_bind_s(TempBrowseLDAPHandle, BrowseLDAPBindDN, LDAP_SASL_SIMPLE, &bval, NULL, NULL, NULL); - -# else - rc = ldap_bind_s(TempBrowseLDAPHandle, BrowseLDAPBindDN, - BrowseLDAPPassword, LDAP_AUTH_SIMPLE); -# endif /* LDAP_API_VERSION > 3000 */ - - if (rc != LDAP_SUCCESS) - { - cupsdLogMessage(CUPSD_LOG_ERROR, "LDAP bind failed with error %d: %s", - rc, ldap_err2string(rc)); - -# if defined(HAVE_LDAP_SSL) && defined (HAVE_MOZILLA_LDAP) - if (ldap_ssl && (rc == LDAP_SERVER_DOWN || rc == LDAP_CONNECT_ERROR)) - { - ssl_err = PORT_GetError(); - if (ssl_err != 0) - cupsdLogMessage(CUPSD_LOG_ERROR, "LDAP SSL error %d: %s", ssl_err, - ldapssl_err2string(ssl_err)); - } -# endif /* defined(HAVE_LDAP_SSL) && defined (HAVE_MOZILLA_LDAP) */ - - ldap_disconnect(TempBrowseLDAPHandle); - - return (NULL); - } - - cupsdLogMessage(CUPSD_LOG_INFO, "LDAP connection established"); - - return (TempBrowseLDAPHandle); -} - - -/* - * 'ldap_reconnect()' - Reconnect to LDAP Server - */ - -static LDAP * /* O - New LDAP handle */ -ldap_reconnect(void) -{ - LDAP *TempBrowseLDAPHandle = NULL; /* Temp Handle to LDAP server */ - - - /* - * Get a new LDAP Handle and replace the global Handle - * if the new connection was successful. - */ - - cupsdLogMessage(CUPSD_LOG_INFO, "Try LDAP reconnect..."); - - TempBrowseLDAPHandle = ldap_connect(); - - if (TempBrowseLDAPHandle != NULL) - { - if (BrowseLDAPHandle != NULL) - ldap_disconnect(BrowseLDAPHandle); - - BrowseLDAPHandle = TempBrowseLDAPHandle; - } - - return (BrowseLDAPHandle); -} - - -/* - * 'ldap_disconnect()' - Disconnect from LDAP Server - */ - -static void -ldap_disconnect(LDAP *ld) /* I - LDAP handle */ -{ - int rc; /* Return code */ - - - /* - * Close LDAP handle... - */ - -# if defined(HAVE_OPENLDAP) && LDAP_API_VERSION > 3000 - rc = ldap_unbind_ext_s(ld, NULL, NULL); -# else - rc = ldap_unbind_s(ld); -# endif /* defined(HAVE_OPENLDAP) && LDAP_API_VERSION > 3000 */ - - if (rc != LDAP_SUCCESS) - cupsdLogMessage(CUPSD_LOG_ERROR, - "Unbind from LDAP server failed with status %d: %s", - rc, ldap_err2string(rc)); -} -#endif /* HAVE_LDAP */ - - -/* - * 'cupsdStartBrowsing()' - Start sending and receiving broadcast information. - */ - -void -cupsdStartBrowsing(void) -{ - int val; /* Socket option value */ - struct sockaddr_in addr; /* Broadcast address */ - cupsd_printer_t *p; /* Current printer */ - - - BrowseNext = NULL; - - if (!Browsing || !(BrowseLocalProtocols | BrowseRemoteProtocols)) - return; - - if ((BrowseLocalProtocols | BrowseRemoteProtocols) & BROWSE_CUPS) - { - if (BrowseSocket < 0) - { - /* - * Create the broadcast socket... - */ - - if ((BrowseSocket = socket(AF_INET, SOCK_DGRAM, 0)) < 0) - { - cupsdLogMessage(CUPSD_LOG_ERROR, - "Unable to create broadcast socket - %s.", - strerror(errno)); - BrowseLocalProtocols &= ~BROWSE_CUPS; - BrowseRemoteProtocols &= ~BROWSE_CUPS; - - if (FatalErrors & CUPSD_FATAL_BROWSE) - cupsdEndProcess(getpid(), 0); - } - } - - if (BrowseSocket >= 0) - { - /* - * Bind the socket to browse port... - */ - - memset(&addr, 0, sizeof(addr)); - addr.sin_addr.s_addr = htonl(INADDR_ANY); - addr.sin_family = AF_INET; - addr.sin_port = htons(BrowsePort); - - if (bind(BrowseSocket, (struct sockaddr *)&addr, sizeof(addr))) - { - cupsdLogMessage(CUPSD_LOG_ERROR, - "Unable to bind broadcast socket - %s.", - strerror(errno)); - -#ifdef WIN32 - closesocket(BrowseSocket); -#else - close(BrowseSocket); -#endif /* WIN32 */ - - BrowseSocket = -1; - BrowseLocalProtocols &= ~BROWSE_CUPS; - BrowseRemoteProtocols &= ~BROWSE_CUPS; - - if (FatalErrors & CUPSD_FATAL_BROWSE) - cupsdEndProcess(getpid(), 0); - } - } - - if (BrowseSocket >= 0) - { - /* - * Set the "broadcast" flag... - */ - - val = 1; - if (setsockopt(BrowseSocket, SOL_SOCKET, SO_BROADCAST, &val, sizeof(val))) - { - cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to set broadcast mode - %s.", - strerror(errno)); - -#ifdef WIN32 - closesocket(BrowseSocket); -#else - close(BrowseSocket); -#endif /* WIN32 */ - - BrowseSocket = -1; - BrowseLocalProtocols &= ~BROWSE_CUPS; - BrowseRemoteProtocols &= ~BROWSE_CUPS; - - if (FatalErrors & CUPSD_FATAL_BROWSE) - cupsdEndProcess(getpid(), 0); - } - } - - if (BrowseSocket >= 0) - { - /* - * Close the socket on exec... - */ - - fcntl(BrowseSocket, F_SETFD, fcntl(BrowseSocket, F_GETFD) | FD_CLOEXEC); - - /* - * Finally, add the socket to the input selection set as needed... - */ - - if (BrowseRemoteProtocols & BROWSE_CUPS) - { - /* - * We only listen if we want remote printers... - */ - - cupsdAddSelect(BrowseSocket, (cupsd_selfunc_t)update_cups_browse, - NULL, NULL); - } - } - } - else - BrowseSocket = -1; - -#ifdef HAVE_DNSSD - if ((BrowseLocalProtocols | BrowseRemoteProtocols) & BROWSE_DNSSD) - { - DNSServiceErrorType error; /* Error from service creation */ - cupsd_listener_t *lis; /* Current listening socket */ - - - /* - * First create a "master" connection for all registrations... - */ - - if ((error = DNSServiceCreateConnection(&DNSSDRef)) - != kDNSServiceErr_NoError) - { - cupsdLogMessage(CUPSD_LOG_ERROR, - "Unable to create master DNS-SD reference: %d", error); - - if (FatalErrors & CUPSD_FATAL_BROWSE) - cupsdEndProcess(getpid(), 0); - } - else - { - /* - * Add the master connection to the select list... - */ - - int fd = DNSServiceRefSockFD(DNSSDRef); - - fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC); - - cupsdAddSelect(fd, (cupsd_selfunc_t)dnssdUpdate, NULL, NULL); - - /* - * Then get the port we use for registrations. If we are not listening - * on any non-local ports, there is no sense sharing local printers via - * Bonjour... - */ - - DNSSDPort = 0; - - for (lis = (cupsd_listener_t *)cupsArrayFirst(Listeners); - lis; - lis = (cupsd_listener_t *)cupsArrayNext(Listeners)) - { - if (httpAddrLocalhost(&(lis->address))) - continue; - - DNSSDPort = _httpAddrPort(&(lis->address)); - break; - } - - /* - * Create an array to track the printers we share... - */ - - if (BrowseRemoteProtocols & BROWSE_DNSSD) - DNSSDPrinters = cupsArrayNew((cups_array_func_t)dnssdComparePrinters, - NULL); - - /* - * Set the computer name and register the web interface... - */ - - cupsdUpdateDNSSDName(); - } - } -#endif /* HAVE_DNSSD */ - -#ifdef HAVE_LIBSLP - if ((BrowseLocalProtocols | BrowseRemoteProtocols) & BROWSE_SLP) - { - /* - * Open SLP handle... - */ - - if (SLPOpen("en", SLP_FALSE, &BrowseSLPHandle) != SLP_OK) - { - cupsdLogMessage(CUPSD_LOG_ERROR, - "Unable to open an SLP handle; disabling SLP browsing!"); - BrowseLocalProtocols &= ~BROWSE_SLP; - BrowseRemoteProtocols &= ~BROWSE_SLP; - BrowseSLPHandle = NULL; - - if (FatalErrors & CUPSD_FATAL_BROWSE) - cupsdEndProcess(getpid(), 0); - } - - BrowseSLPRefresh = 0; - } - else - BrowseSLPHandle = NULL; -#endif /* HAVE_LIBSLP */ - -#ifdef HAVE_LDAP - if ((BrowseLocalProtocols | BrowseRemoteProtocols) & BROWSE_LDAP) - { - if (!BrowseLDAPDN) - { - cupsdLogMessage(CUPSD_LOG_ERROR, - "Need to set BrowseLDAPDN to use LDAP browsing!"); - BrowseLocalProtocols &= ~BROWSE_LDAP; - BrowseRemoteProtocols &= ~BROWSE_LDAP; - - if (FatalErrors & CUPSD_FATAL_BROWSE) - cupsdEndProcess(getpid(), 0); - } - else - { - /* - * Open LDAP handle... - */ - - if ((BrowseLDAPHandle = ldap_connect()) == NULL && - (FatalErrors & CUPSD_FATAL_BROWSE)) - cupsdEndProcess(getpid(), 0); - } - - BrowseLDAPRefresh = 0; - } -#endif /* HAVE_LDAP */ - - /* - * Enable LPD and SMB printer sharing as needed through external programs... - */ - - if (BrowseLocalProtocols & BROWSE_LPD) - update_lpd(1); - - if (BrowseLocalProtocols & BROWSE_SMB) - update_smb(1); - - /* - * Register the individual printers - */ - - for (p = (cupsd_printer_t *)cupsArrayFirst(Printers); - p; - p = (cupsd_printer_t *)cupsArrayNext(Printers)) - if (!(p->type & (CUPS_PRINTER_REMOTE | CUPS_PRINTER_IMPLICIT | - CUPS_PRINTER_SCANNER))) - cupsdRegisterPrinter(p); -} - - -/* - * 'cupsdStartPolling()' - Start polling servers as needed. - */ - -void -cupsdStartPolling(void) -{ - int i; /* Looping var */ - cupsd_dirsvc_poll_t *pollp; /* Current polling server */ - char polld[1024]; /* Poll daemon path */ - char sport[255]; /* Server port */ - char bport[255]; /* Browser port */ - char interval[255]; /* Poll interval */ - int statusfds[2]; /* Status pipe */ - char *argv[6]; /* Arguments */ - char *envp[100]; /* Environment */ - - - /* - * Don't do anything if we aren't polling... - */ - - if (NumPolled == 0 || BrowseSocket < 0) - { - PollPipe = -1; - PollStatusBuffer = NULL; - return; - } - - /* - * Setup string arguments for polld, port and interval options. - */ - - snprintf(polld, sizeof(polld), "%s/daemon/cups-polld", ServerBin); - - sprintf(bport, "%d", BrowsePort); - - if (BrowseInterval) - sprintf(interval, "%d", BrowseInterval); - else - strcpy(interval, "30"); - - argv[0] = "cups-polld"; - argv[2] = sport; - argv[3] = interval; - argv[4] = bport; - argv[5] = NULL; - - cupsdLoadEnv(envp, (int)(sizeof(envp) / sizeof(envp[0]))); - - /* - * Create a pipe that receives the status messages from each - * polling daemon... - */ - - if (cupsdOpenPipe(statusfds)) - { - cupsdLogMessage(CUPSD_LOG_ERROR, - "Unable to create polling status pipes - %s.", - strerror(errno)); - PollPipe = -1; - PollStatusBuffer = NULL; - return; - } - - PollPipe = statusfds[0]; - PollStatusBuffer = cupsdStatBufNew(PollPipe, "[Poll]"); - - /* - * Run each polling daemon, redirecting stderr to the polling pipe... - */ - - for (i = 0, pollp = Polled; i < NumPolled; i ++, pollp ++) - { - sprintf(sport, "%d", pollp->port); - - argv[1] = pollp->hostname; - - if (cupsdStartProcess(polld, argv, envp, -1, -1, statusfds[1], -1, -1, - 0, DefaultProfile, NULL, &(pollp->pid)) < 0) - { - cupsdLogMessage(CUPSD_LOG_ERROR, - "cupsdStartPolling: Unable to fork polling daemon - %s", - strerror(errno)); - pollp->pid = 0; - break; - } - else - cupsdLogMessage(CUPSD_LOG_DEBUG, - "cupsdStartPolling: Started polling daemon for %s:%d, pid = %d", - pollp->hostname, pollp->port, pollp->pid); - } - - close(statusfds[1]); - - /* - * Finally, add the pipe to the input selection set... - */ - - cupsdAddSelect(PollPipe, (cupsd_selfunc_t)update_polling, NULL, NULL); -} - - -/* - * 'cupsdStopBrowsing()' - Stop sending and receiving broadcast information. - */ - -void -cupsdStopBrowsing(void) -{ - cupsd_printer_t *p; /* Current printer */ - - - if (!Browsing || !(BrowseLocalProtocols | BrowseRemoteProtocols)) - return; - - /* - * De-register the individual printers - */ - - for (p = (cupsd_printer_t *)cupsArrayFirst(Printers); - p; - p = (cupsd_printer_t *)cupsArrayNext(Printers)) - if (!(p->type & (CUPS_PRINTER_REMOTE | CUPS_PRINTER_IMPLICIT | - CUPS_PRINTER_SCANNER))) - cupsdDeregisterPrinter(p, 1); - - /* - * Shut down browsing sockets... - */ - - if (((BrowseLocalProtocols | BrowseRemoteProtocols) & BROWSE_CUPS) && - BrowseSocket >= 0) - { - /* - * Close the socket and remove it from the input selection set. - */ - -#ifdef WIN32 - closesocket(BrowseSocket); -#else - close(BrowseSocket); -#endif /* WIN32 */ - - cupsdRemoveSelect(BrowseSocket); - BrowseSocket = -1; - } - -#ifdef HAVE_DNSSD - if ((BrowseLocalProtocols & BROWSE_DNSSD) && DNSSDRef) - dnssdStop(); -#endif /* HAVE_DNSSD */ - -#ifdef HAVE_LIBSLP - if (((BrowseLocalProtocols | BrowseRemoteProtocols) & BROWSE_SLP) && - BrowseSLPHandle) - { - /* - * Close SLP handle... - */ - - SLPClose(BrowseSLPHandle); - BrowseSLPHandle = NULL; - } -#endif /* HAVE_LIBSLP */ - -#ifdef HAVE_LDAP - if (((BrowseLocalProtocols | BrowseRemoteProtocols) & BROWSE_LDAP) && - BrowseLDAPHandle) - { - ldap_dereg_ou(ServerName, BrowseLDAPDN); - ldap_disconnect(BrowseLDAPHandle); - BrowseLDAPHandle = NULL; - } -#endif /* HAVE_OPENLDAP */ - - /* - * Disable LPD and SMB printer sharing as needed through external programs... - */ - - if (BrowseLocalProtocols & BROWSE_LPD) - update_lpd(0); - - if (BrowseLocalProtocols & BROWSE_SMB) - update_smb(0); -} - - -/* - * 'cupsdStopPolling()' - Stop polling servers as needed. - */ - -void -cupsdStopPolling(void) -{ - int i; /* Looping var */ - cupsd_dirsvc_poll_t *pollp; /* Current polling server */ - - - if (PollPipe >= 0) - { - cupsdStatBufDelete(PollStatusBuffer); - close(PollPipe); - - cupsdRemoveSelect(PollPipe); - - PollPipe = -1; - PollStatusBuffer = NULL; - } - - for (i = 0, pollp = Polled; i < NumPolled; i ++, pollp ++) - if (pollp->pid) - cupsdEndProcess(pollp->pid, 0); -} - - -#ifdef HAVE_DNSSD -/* - * 'cupsdUpdateDNSSDName()' - Update the computer name we use for browsing... - */ - -void -cupsdUpdateDNSSDName(void) -{ - DNSServiceErrorType error; /* Error from service creation */ - char webif[1024]; /* Web interface share name */ -# ifdef HAVE_SYSTEMCONFIGURATION - SCDynamicStoreRef sc; /* Context for dynamic store */ - CFDictionaryRef btmm; /* Back-to-My-Mac domains */ - CFStringEncoding nameEncoding; /* Encoding of computer name */ - CFStringRef nameRef; /* Host name CFString */ - char nameBuffer[1024]; /* C-string buffer */ -# endif /* HAVE_SYSTEMCONFIGURATION */ - - - /* - * Only share the web interface and printers when non-local listening is - * enabled... - */ - - - if (!DNSSDPort) - return; - - /* - * Get the computer name as a c-string... - */ - -# ifdef HAVE_SYSTEMCONFIGURATION - sc = SCDynamicStoreCreate(kCFAllocatorDefault, CFSTR("cupsd"), NULL, NULL); - - if (sc) - { - /* - * Get the computer name from the dynamic store... - */ - - cupsdClearString(&DNSSDComputerName); - - if ((nameRef = SCDynamicStoreCopyComputerName(sc, &nameEncoding)) != NULL) - { - if (CFStringGetCString(nameRef, nameBuffer, sizeof(nameBuffer), - kCFStringEncodingUTF8)) - { - cupsdLogMessage(CUPSD_LOG_DEBUG, - "Dynamic store computer name is \"%s\".", nameBuffer); - cupsdSetString(&DNSSDComputerName, nameBuffer); - } - - CFRelease(nameRef); - } - - if (!DNSSDComputerName) - { - /* - * Use the ServerName instead... - */ - - cupsdLogMessage(CUPSD_LOG_DEBUG, - "Using ServerName \"%s\" as computer name.", ServerName); - cupsdSetString(&DNSSDComputerName, ServerName); - } - - /* - * Get the local hostname from the dynamic store... - */ - - cupsdClearString(&DNSSDHostName); - - if ((nameRef = SCDynamicStoreCopyLocalHostName(sc)) != NULL) - { - if (CFStringGetCString(nameRef, nameBuffer, sizeof(nameBuffer), - kCFStringEncodingUTF8)) - { - cupsdLogMessage(CUPSD_LOG_DEBUG, - "Dynamic store host name is \"%s\".", nameBuffer); - cupsdSetString(&DNSSDHostName, nameBuffer); - } - - CFRelease(nameRef); - } - - if (!DNSSDHostName) - { - /* - * Use the ServerName instead... - */ - - cupsdLogMessage(CUPSD_LOG_DEBUG, - "Using ServerName \"%s\" as host name.", ServerName); - cupsdSetString(&DNSSDHostName, ServerName); - } - - /* - * Get any Back-to-My-Mac domains and add them as aliases... - */ - - cupsdFreeAliases(DNSSDAlias); - DNSSDAlias = NULL; - - btmm = SCDynamicStoreCopyValue(sc, CFSTR("Setup:/Network/BackToMyMac")); - if (btmm && CFGetTypeID(btmm) == CFDictionaryGetTypeID()) - { - cupsdLogMessage(CUPSD_LOG_DEBUG, "%d Back to My Mac aliases to add.", - (int)CFDictionaryGetCount(btmm)); - CFDictionaryApplyFunction(btmm, dnssdAddAlias, NULL); - } - else if (btmm) - cupsdLogMessage(CUPSD_LOG_ERROR, - "Bad Back to My Mac data in dynamic store!"); - else - cupsdLogMessage(CUPSD_LOG_DEBUG, "No Back to My Mac aliases to add."); - - if (btmm) - CFRelease(btmm); - - CFRelease(sc); - } - else -# endif /* HAVE_SYSTEMCONFIGURATION */ - { - cupsdSetString(&DNSSDComputerName, ServerName); - cupsdSetString(&DNSSDHostName, ServerName); - } - - /* - * Then (re)register the web interface if enabled... - */ - - if (BrowseWebIF) - { - if (DNSSDComputerName) - snprintf(webif, sizeof(webif), "CUPS @ %s", DNSSDComputerName); - else - strlcpy(webif, "CUPS Web Interface", sizeof(webif)); - - if (WebIFRef) - DNSServiceRefDeallocate(WebIFRef); - - WebIFRef = DNSSDRef; - if ((error = DNSServiceRegister(&WebIFRef, - kDNSServiceFlagsShareConnection, - 0, webif, "_http._tcp", NULL, - NULL, htons(DNSSDPort), 7, - "\006path=/", dnssdRegisterCallback, - NULL)) != kDNSServiceErr_NoError) - cupsdLogMessage(CUPSD_LOG_ERROR, - "DNS-SD web interface registration failed: %d", error); - } -} -#endif /* HAVE_DNSSD */ - - -#ifdef HAVE_LDAP -/* - * 'cupsdUpdateLDAPBrowse()' - Scan for new printers via LDAP... - */ - -void -cupsdUpdateLDAPBrowse(void) -{ - char uri[HTTP_MAX_URI], /* Printer URI */ - host[HTTP_MAX_URI], /* Hostname */ - resource[HTTP_MAX_URI], /* Resource path */ - location[1024], /* Printer location */ - info[1024], /* Printer information */ - make_model[1024], /* Printer make and model */ - type_num[30]; /* Printer type number */ - int type; /* Printer type */ - int rc; /* LDAP status */ - int limit; /* Size limit */ - LDAPMessage *res, /* LDAP search results */ - *e; /* Current entry from search */ - - cupsdLogMessage(CUPSD_LOG_DEBUG2, "UpdateLDAPBrowse: %s", ServerName); - - BrowseLDAPRefresh = time(NULL) + BrowseInterval; - - /* - * Reconnect if LDAP Handle is invalid... - */ - - if (! BrowseLDAPHandle) - { - ldap_reconnect(); - return; - } - - /* - * Search for cups printers in LDAP directory... - */ - - rc = ldap_search_rec(BrowseLDAPHandle, BrowseLDAPDN, LDAP_SCOPE_SUBTREE, - "(objectclass=cupsPrinter)", (char **)ldap_attrs, 0, &res); - - /* - * If ldap search was successfull then exit function - * and temporary disable LDAP updates... - */ - - if (rc != LDAP_SUCCESS) - { - if (BrowseLDAPUpdate && ((rc == LDAP_SERVER_DOWN) || (rc == LDAP_CONNECT_ERROR))) - { - BrowseLDAPUpdate = FALSE; - cupsdLogMessage(CUPSD_LOG_INFO, - "LDAP update temporary disabled"); - } - return; - } - - /* - * If LDAP updates were disabled, we will reenable them... - */ - - if (! BrowseLDAPUpdate) - { - BrowseLDAPUpdate = TRUE; - cupsdLogMessage(CUPSD_LOG_INFO, - "LDAP update enabled"); - } - - /* - * Count LDAP entries and return if no entry exist... - */ - - limit = ldap_count_entries(BrowseLDAPHandle, res); - cupsdLogMessage(CUPSD_LOG_DEBUG2, "LDAP search returned %d entries", limit); - if (limit < 1) - { - ldap_freeres(res); - return; - } - - /* - * Loop through the available printers... - */ - - for (e = ldap_first_entry(BrowseLDAPHandle, res); - e; - e = ldap_next_entry(BrowseLDAPHandle, e)) - { - /* - * Get the required values from this entry... - */ - - if (ldap_getval_firststring(BrowseLDAPHandle, e, - "printerDescription", info, sizeof(info)) == -1) - continue; - - if (ldap_getval_firststring(BrowseLDAPHandle, e, - "printerLocation", location, sizeof(location)) == -1) - continue; - - if (ldap_getval_firststring(BrowseLDAPHandle, e, - "printerMakeAndModel", make_model, sizeof(make_model)) == -1) - continue; - - if (ldap_getval_firststring(BrowseLDAPHandle, e, - "printerType", type_num, sizeof(type_num)) == -1) - continue; - - type = atoi(type_num); - - if (ldap_getval_firststring(BrowseLDAPHandle, e, - "printerURI", uri, sizeof(uri)) == -1) - continue; - - /* - * Process the entry as browse data... - */ - - if (!is_local_queue(uri, host, sizeof(host), resource, sizeof(resource))) - process_browse_data(uri, host, resource, type, IPP_PRINTER_IDLE, - location, info, make_model, 0, NULL); - - } - - ldap_freeres(res); -} -#endif /* HAVE_LDAP */ - - -#ifdef HAVE_LIBSLP -/* - * 'cupsdUpdateSLPBrowse()' - Get browsing information via SLP. - */ - -void -cupsdUpdateSLPBrowse(void) -{ - slpsrvurl_t *s, /* Temporary list of service URLs */ - *next; /* Next service in list */ - cupsd_printer_t p; /* Printer information */ - const char *uri; /* Pointer to printer URI */ - char host[HTTP_MAX_URI], /* Host portion of URI */ - resource[HTTP_MAX_URI]; /* Resource portion of URI */ - - - /* - * Reset the refresh time... - */ - - BrowseSLPRefresh = time(NULL) + BrowseInterval; - - /* - * Poll for remote printers using SLP... - */ - - s = NULL; - - SLPFindSrvs(BrowseSLPHandle, SLP_CUPS_SRVTYPE, "", "", - slp_url_callback, &s); - - /* - * Loop through the list of available printers... - */ - - for (; s; s = next) - { - /* - * Save the "next" pointer... - */ - - next = s->next; - - /* - * Load a cupsd_printer_t structure with the SLP service attributes... - */ - - SLPFindAttrs(BrowseSLPHandle, s->url, "", "", slp_attr_callback, &p); - - /* - * Process this printer entry... - */ - - uri = s->url + SLP_CUPS_SRVLEN + 1; - - if (!strncmp(uri, "http://", 7) || !strncmp(uri, "ipp://", 6)) - { - /* - * Pull the URI apart to see if this is a local or remote printer... - */ - - if (!is_local_queue(uri, host, sizeof(host), resource, sizeof(resource))) - process_browse_data(uri, host, resource, p.type, IPP_PRINTER_IDLE, - p.location, p.info, p.make_model, 0, NULL); - } - - /* - * Free this listing... - */ - - cupsdClearString(&p.info); - cupsdClearString(&p.location); - cupsdClearString(&p.make_model); - - free(s); - } -} -#endif /* HAVE_LIBSLP */ - - -/* - * 'dequote()' - Remote quotes from a string. - */ - -static char * /* O - Dequoted string */ -dequote(char *d, /* I - Destination string */ - const char *s, /* I - Source string */ - int dlen) /* I - Destination length */ -{ - char *dptr; /* Pointer into destination */ - - - if (s) - { - for (dptr = d, dlen --; *s && dlen > 0; s ++) - if (*s != '\"') - { - *dptr++ = *s; - dlen --; - } - - *dptr = '\0'; - } - else - *d = '\0'; - - return (d); -} - - -#ifdef HAVE_DNSSD -# ifdef HAVE_COREFOUNDATION -/* - * 'dnssdAddAlias()' - Add a DNS-SD alias name. - */ - -static void -dnssdAddAlias(const void *key, /* I - Key */ - const void *value, /* I - Value (domain) */ - void *context) /* I - Unused */ -{ - char valueStr[1024], /* Domain string */ - hostname[1024]; /* Complete hostname */ - - - (void)key; - (void)context; - - if (CFGetTypeID((CFStringRef)value) == CFStringGetTypeID() && - CFStringGetCString((CFStringRef)value, valueStr, sizeof(valueStr), - kCFStringEncodingUTF8)) - { - snprintf(hostname, sizeof(hostname), "%s.%s", DNSSDHostName, valueStr); - if (!DNSSDAlias) - DNSSDAlias = cupsArrayNew(NULL, NULL); - - cupsdAddAlias(DNSSDAlias, hostname); - cupsdLogMessage(CUPSD_LOG_DEBUG, "Added Back to My Mac ServerAlias %s", - hostname); - } - else - cupsdLogMessage(CUPSD_LOG_ERROR, - "Bad Back to My Mac domain in dynamic store!"); -} -# endif /* HAVE_COREFOUNDATION */ - - -/* - * 'dnssdBuildTxtRecord()' - Build a TXT record from printer info. - */ - -static char * /* O - TXT record */ -dnssdBuildTxtRecord( - int *txt_len, /* O - TXT record length */ - cupsd_printer_t *p, /* I - Printer information */ - int for_lpd) /* I - 1 = LPD, 0 = IPP */ -{ - int i; /* Looping var */ - char admin_hostname[256], /* .local hostname for admin page */ - adminurl_str[256], /* URL for the admin page */ - type_str[32], /* Type to string buffer */ - state_str[32], /* State to string buffer */ - rp_str[1024], /* Queue name string buffer */ - air_str[1024], /* auth-info-required string buffer */ - *keyvalue[32][2]; /* Table of key/value pairs */ - - - /* - * Load up the key value pairs... - */ - - i = 0; - - keyvalue[i ][0] = "txtvers"; - keyvalue[i++][1] = "1"; - - keyvalue[i ][0] = "qtotal"; - keyvalue[i++][1] = "1"; - - keyvalue[i ][0] = "rp"; - keyvalue[i++][1] = rp_str; - if (for_lpd) - strlcpy(rp_str, p->name, sizeof(rp_str)); - else - snprintf(rp_str, sizeof(rp_str), "%s/%s", - (p->type & CUPS_PRINTER_CLASS) ? "classes" : "printers", p->name); - - keyvalue[i ][0] = "ty"; - keyvalue[i++][1] = p->make_model ? p->make_model : "Unknown"; - - snprintf(admin_hostname, sizeof(admin_hostname), "%s.local.", DNSSDHostName); - httpAssembleURIf(HTTP_URI_CODING_ALL, adminurl_str, sizeof(adminurl_str), - "http", NULL, admin_hostname, DNSSDPort, "/%s/%s", - (p->type & CUPS_PRINTER_CLASS) ? "classes" : "printers", - p->name); - keyvalue[i ][0] = "adminurl"; - keyvalue[i++][1] = adminurl_str; - - keyvalue[i ][0] = "note"; - keyvalue[i++][1] = p->location ? p->location : ""; - - keyvalue[i ][0] = "priority"; - keyvalue[i++][1] = for_lpd ? "100" : "0"; - - keyvalue[i ][0] = "product"; - keyvalue[i++][1] = p->pc && p->pc->product ? p->pc->product : "Unknown"; - - keyvalue[i ][0] = "pdl"; - keyvalue[i++][1] = p->pdl ? p->pdl : "application/postscript"; - - if (get_auth_info_required(p, air_str, sizeof(air_str))) - { - keyvalue[i ][0] = "air"; - keyvalue[i++][1] = air_str; - } - - keyvalue[i ][0] = "UUID"; - keyvalue[i++][1] = p->uuid + 9; - -#ifdef HAVE_SSL - keyvalue[i ][0] = "TLS"; - keyvalue[i++][1] = "1.2"; -#endif /* HAVE_SSL */ - - keyvalue[i ][0] = "Transparent"; - keyvalue[i++][1] = "F"; - - keyvalue[i ][0] = "Binary"; - keyvalue[i++][1] = "F"; - - keyvalue[i ][0] = "Fax"; - keyvalue[i++][1] = (p->type & CUPS_PRINTER_FAX) ? "T" : "F"; - - keyvalue[i ][0] = "Color"; - keyvalue[i++][1] = (p->type & CUPS_PRINTER_COLOR) ? "T" : "F"; - - keyvalue[i ][0] = "Duplex"; - keyvalue[i++][1] = (p->type & CUPS_PRINTER_DUPLEX) ? "T" : "F"; - - keyvalue[i ][0] = "Staple"; - keyvalue[i++][1] = (p->type & CUPS_PRINTER_STAPLE) ? "T" : "F"; - - keyvalue[i ][0] = "Copies"; - keyvalue[i++][1] = (p->type & CUPS_PRINTER_COPIES) ? "T" : "F"; - - keyvalue[i ][0] = "Collate"; - keyvalue[i++][1] = (p->type & CUPS_PRINTER_COLLATE) ? "T" : "F"; - - keyvalue[i ][0] = "Punch"; - keyvalue[i++][1] = (p->type & CUPS_PRINTER_PUNCH) ? "T" : "F"; - - keyvalue[i ][0] = "Bind"; - keyvalue[i++][1] = (p->type & CUPS_PRINTER_BIND) ? "T" : "F"; - - keyvalue[i ][0] = "Sort"; - keyvalue[i++][1] = (p->type & CUPS_PRINTER_SORT) ? "T" : "F"; - - keyvalue[i ][0] = "Scan"; - keyvalue[i++][1] = (p->type & CUPS_PRINTER_MFP) ? "T" : "F"; - - snprintf(type_str, sizeof(type_str), "0x%X", p->type | CUPS_PRINTER_REMOTE); - snprintf(state_str, sizeof(state_str), "%d", p->state); - - keyvalue[i ][0] = "printer-state"; - keyvalue[i++][1] = state_str; - - keyvalue[i ][0] = "printer-type"; - keyvalue[i++][1] = type_str; - - /* - * Then pack them into a proper txt record... - */ - - return (dnssdPackTxtRecord(txt_len, keyvalue, i)); -} - - -/* - * 'dnssdComparePrinters()' - Compare the registered names of two printers. - */ - -static int /* O - Result of comparison */ -dnssdComparePrinters(cupsd_printer_t *a,/* I - First printer */ - cupsd_printer_t *b)/* I - Second printer */ -{ - return (_cups_strcasecmp(a->reg_name, b->reg_name)); -} - - -/* - * 'dnssdDeregisterPrinter()' - Stop sending broadcast information for a - * printer. - */ - -static void -dnssdDeregisterPrinter( - cupsd_printer_t *p) /* I - Printer */ -{ - cupsdLogMessage(CUPSD_LOG_DEBUG2, "dnssdDeregisterPrinter(%s)", p->name); - - /* - * Closing the socket deregisters the service - */ - - if (p->ipp_ref) - { - DNSServiceRefDeallocate(p->ipp_ref); - p->ipp_ref = NULL; - } - - if (p->ipp_txt) - { - /* - * p->ipp_txt is malloc'd, not _cupsStrAlloc'd... - */ - - free(p->ipp_txt); - p->ipp_txt = NULL; - } - - if (p->printer_ref) - { - DNSServiceRefDeallocate(p->printer_ref); - p->printer_ref = NULL; - } - - if (p->printer_txt) - { - /* - * p->printer_txt is malloc'd, not _cupsStrAlloc'd... - */ - - free(p->printer_txt); - p->printer_txt = NULL; - } - - /* - * Remove the printer from the array of DNS-SD printers, then clear the - * registered name... - */ - - cupsArrayRemove(DNSSDPrinters, p); - cupsdClearString(&p->reg_name); -} - - -/* - * 'dnssdPackTxtRecord()' - Pack an array of key/value pairs into the - * TXT record format. - */ - -static char * /* O - TXT record */ -dnssdPackTxtRecord(int *txt_len, /* O - TXT record length */ - char *keyvalue[][2], /* I - Table of key value pairs */ - int count) /* I - Items in table */ -{ - int i; /* Looping var */ - int length; /* Length of TXT record */ - int length2; /* Length of value */ - char *txtRecord; /* TXT record buffer */ - char *cursor; /* Looping pointer */ - - - /* - * Calculate the buffer size - */ - - if (count <= 0) - return (NULL); - - for (length = i = 0; i < count; i++) - length += 1 + strlen(keyvalue[i][0]) + - (keyvalue[i][1] ? 1 + strlen(keyvalue[i][1]) : 0); - - /* - * Allocate and fill it - */ - - txtRecord = malloc(length); - if (txtRecord) - { - *txt_len = length; - - for (cursor = txtRecord, i = 0; i < count; i++) - { - /* - * Drop in the p-string style length byte followed by the data - */ - - length = strlen(keyvalue[i][0]); - length2 = keyvalue[i][1] ? 1 + strlen(keyvalue[i][1]) : 0; - - *cursor++ = (unsigned char)(length + length2); - - memcpy(cursor, keyvalue[i][0], length); - cursor += length; - - if (length2) - { - length2 --; - *cursor++ = '='; - memcpy(cursor, keyvalue[i][1], length2); - cursor += length2; - } - } - } - - return (txtRecord); -} - - -/* - * 'dnssdRegisterCallback()' - DNSServiceRegister callback. - */ - -static void -dnssdRegisterCallback( - DNSServiceRef sdRef, /* I - DNS Service reference */ - DNSServiceFlags flags, /* I - Reserved for future use */ - DNSServiceErrorType errorCode, /* I - Error code */ - const char *name, /* I - Service name */ - const char *regtype, /* I - Service type */ - const char *domain, /* I - Domain. ".local" for now */ - void *context) /* I - User-defined context */ -{ - cupsd_printer_t *p = (cupsd_printer_t *)context; - /* Current printer */ - - - (void)sdRef; - (void)flags; - (void)domain; - - cupsdLogMessage(CUPSD_LOG_DEBUG2, "dnssdRegisterCallback(%s, %s) for %s (%s)", - name, regtype, p ? p->name : "Web Interface", - p ? (p->reg_name ? p->reg_name : "(null)") : "NA"); - - if (errorCode) - { - cupsdLogMessage(CUPSD_LOG_ERROR, - "DNSServiceRegister failed with error %d", (int)errorCode); - return; - } - else if (p && (!p->reg_name || _cups_strcasecmp(name, p->reg_name))) - { - cupsdLogMessage(CUPSD_LOG_INFO, "Using service name \"%s\" for \"%s\"", - name, p->name); - - cupsArrayRemove(DNSSDPrinters, p); - cupsdSetString(&p->reg_name, name); - cupsArrayAdd(DNSSDPrinters, p); - - LastEvent |= CUPSD_EVENT_PRINTER_MODIFIED; - } -} - - -/* - * 'dnssdRegisterPrinter()' - Start sending broadcast information for a printer - * or update the broadcast contents. - */ - -static void -dnssdRegisterPrinter(cupsd_printer_t *p)/* I - Printer */ -{ - DNSServiceErrorType se; /* dnssd errors */ - char *ipp_txt, /* IPP TXT record buffer */ - *printer_txt, /* LPD TXT record buffer */ - name[1024], /* Service name */ - *nameptr; /* Pointer into name */ - int ipp_len, /* IPP TXT record length */ - printer_len, /* LPD TXT record length */ - printer_port; /* LPD port number */ - const char *regtype; /* Registration type */ - - - cupsdLogMessage(CUPSD_LOG_DEBUG2, "dnssdRegisterPrinter(%s) %s", p->name, - !p->ipp_ref ? "new" : "update"); - - /* - * If per-printer sharing was just disabled make sure we're not - * registered before returning. - */ - - if (!p->shared) - { - dnssdDeregisterPrinter(p); - return; - } - - /* - * The registered name takes the form of " @ "... - */ - - if (p->info && strlen(p->info) > 0) - { - if (DNSSDComputerName) - snprintf(name, sizeof(name), "%s @ %s", p->info, DNSSDComputerName); - else - strlcpy(name, p->info, sizeof(name)); - } - else if (DNSSDComputerName) - snprintf(name, sizeof(name), "%s @ %s", p->name, DNSSDComputerName); - else - strlcpy(name, p->name, sizeof(name)); - - /* - * If an existing printer was renamed, unregister it and start over... - */ - - if (p->reg_name && strcmp(p->reg_name, name)) - dnssdDeregisterPrinter(p); - - if (!p->reg_name) - { - cupsdSetString(&p->reg_name, name); - cupsArrayAdd(DNSSDPrinters, p); - } - - /* - * Register IPP and (optionally) LPD... - */ - - ipp_len = 0; /* anti-compiler-warning-code */ - ipp_txt = dnssdBuildTxtRecord(&ipp_len, p, 0); - - if (p->ipp_ref && - (ipp_len != p->ipp_len || memcmp(ipp_txt, p->ipp_txt, ipp_len))) - { - /* - * Update the existing registration... - */ - - /* A TTL of 0 means use record's original value (Radar 3176248) */ - if ((se = DNSServiceUpdateRecord(p->ipp_ref, NULL, 0, ipp_len, ipp_txt, - 0)) == kDNSServiceErr_NoError) - { - if (p->ipp_txt) - free(p->ipp_txt); - - p->ipp_txt = ipp_txt; - p->ipp_len = ipp_len; - ipp_txt = NULL; - } - else - { - /* - * Failed to update record, lets close this reference and move on... - */ - - cupsdLogMessage(CUPSD_LOG_ERROR, - "Unable to update IPP DNS-SD record for %s - %d", p->name, - se); - - DNSServiceRefDeallocate(p->ipp_ref); - p->ipp_ref = NULL; - } - } - - if (!p->ipp_ref) - { - /* - * Initial registration. Use the _fax-ipp regtype for fax queues... - */ - - regtype = (p->type & CUPS_PRINTER_FAX) ? "_fax-ipp._tcp" : DNSSDRegType; - - cupsdLogMessage(CUPSD_LOG_DEBUG, - "Registering DNS-SD printer %s with name \"%s\" and " - "type \"%s\"", p->name, name, regtype); - - /* - * Register the queue, dropping characters as needed until we succeed... - */ - - nameptr = name + strlen(name); - - do - { - p->ipp_ref = DNSSDRef; - if ((se = DNSServiceRegister(&p->ipp_ref, kDNSServiceFlagsShareConnection, - 0, name, regtype, NULL, NULL, - htons(DNSSDPort), ipp_len, ipp_txt, - dnssdRegisterCallback, - p)) == kDNSServiceErr_BadParam) - { - /* - * Name is too long, drop trailing characters, taking into account - * UTF-8 encoding... - */ - - nameptr --; - - while (nameptr > name && (*nameptr & 0xc0) == 0x80) - nameptr --; - - if (nameptr > name) - *nameptr = '\0'; - } - } - while (se == kDNSServiceErr_BadParam && nameptr > name); - - if (se == kDNSServiceErr_NoError) - { - p->ipp_txt = ipp_txt; - p->ipp_len = ipp_len; - ipp_txt = NULL; - } - else - cupsdLogMessage(CUPSD_LOG_WARN, - "DNS-SD IPP registration of \"%s\" failed: %d", - p->name, se); - } - - if (ipp_txt) - free(ipp_txt); - - if (BrowseLocalProtocols & BROWSE_LPD) - { - printer_len = 0; /* anti-compiler-warning-code */ - printer_port = 515; - printer_txt = dnssdBuildTxtRecord(&printer_len, p, 1); - } - else - { - printer_len = 0; - printer_port = 0; - printer_txt = NULL; - } - - if (p->printer_ref && - (printer_len != p->printer_len || - memcmp(printer_txt, p->printer_txt, printer_len))) - { - /* - * Update the existing registration... - */ - - /* A TTL of 0 means use record's original value (Radar 3176248) */ - if ((se = DNSServiceUpdateRecord(p->printer_ref, NULL, 0, printer_len, - printer_txt, - 0)) == kDNSServiceErr_NoError) - { - if (p->printer_txt) - free(p->printer_txt); - - p->printer_txt = printer_txt; - p->printer_len = printer_len; - printer_txt = NULL; - } - else - { - /* - * Failed to update record, lets close this reference and move on... - */ - - cupsdLogMessage(CUPSD_LOG_ERROR, - "Unable to update LPD DNS-SD record for %s - %d", - p->name, se); - - DNSServiceRefDeallocate(p->printer_ref); - p->printer_ref = NULL; - } - } - - if (!p->printer_ref) - { - /* - * Initial registration... - */ - - cupsdLogMessage(CUPSD_LOG_DEBUG, - "Registering DNS-SD printer %s with name \"%s\" and " - "type \"_printer._tcp\"", p->name, name); - - p->printer_ref = DNSSDRef; - if ((se = DNSServiceRegister(&p->printer_ref, - kDNSServiceFlagsShareConnection, - 0, name, "_printer._tcp", NULL, NULL, - htons(printer_port), printer_len, printer_txt, - dnssdRegisterCallback, - p)) == kDNSServiceErr_NoError) - { - p->printer_txt = printer_txt; - p->printer_len = printer_len; - printer_txt = NULL; - } - else - cupsdLogMessage(CUPSD_LOG_WARN, - "DNS-SD LPD registration of \"%s\" failed: %d", - p->name, se); - } - - if (printer_txt) - free(printer_txt); -} - - -/* - * 'dnssdStop()' - Stop all DNS-SD registrations. - */ - -static void -dnssdStop(void) -{ - cupsd_printer_t *p; /* Current printer */ - - - /* - * De-register the individual printers - */ - - for (p = (cupsd_printer_t *)cupsArrayFirst(Printers); - p; - p = (cupsd_printer_t *)cupsArrayNext(Printers)) - dnssdDeregisterPrinter(p); - - /* - * Shutdown the rest of the service refs... - */ - - if (WebIFRef) - { - DNSServiceRefDeallocate(WebIFRef); - WebIFRef = NULL; - } - - if (RemoteRef) - { - DNSServiceRefDeallocate(RemoteRef); - RemoteRef = NULL; - } - - cupsdRemoveSelect(DNSServiceRefSockFD(DNSSDRef)); - - DNSServiceRefDeallocate(DNSSDRef); - DNSSDRef = NULL; - - cupsArrayDelete(DNSSDPrinters); - DNSSDPrinters = NULL; - - DNSSDPort = 0; -} - - -/* - * 'dnssdUpdate()' - Handle DNS-SD queries. - */ - -static void -dnssdUpdate(void) -{ - DNSServiceErrorType sdErr; /* Service discovery error */ - - - if ((sdErr = DNSServiceProcessResult(DNSSDRef)) != kDNSServiceErr_NoError) - { - cupsdLogMessage(CUPSD_LOG_ERROR, - "DNS Service Discovery registration error %d!", - sdErr); - dnssdStop(); - } -} -#endif /* HAVE_DNSSD */ - - -/* - * 'get_auth_info_required()' - Get the auth-info-required value to advertise. - */ - -static char * /* O - String or NULL if none */ -get_auth_info_required( - cupsd_printer_t *p, /* I - Printer */ - char *buffer, /* I - Value buffer */ - size_t bufsize) /* I - Size of value buffer */ -{ - cupsd_location_t *auth; /* Pointer to authentication element */ - char resource[1024]; /* Printer/class resource path */ - - - /* - * If auth-info-required is set for this printer, return that... - */ - - if (p->num_auth_info_required > 0 && strcmp(p->auth_info_required[0], "none")) - { - int i; /* Looping var */ - char *bufptr; /* Pointer into buffer */ - - for (i = 0, bufptr = buffer; i < p->num_auth_info_required; i ++) - { - if (bufptr >= (buffer + bufsize - 2)) - break; - - if (i) - *bufptr++ = ','; - - strlcpy(bufptr, p->auth_info_required[i], bufsize - (bufptr - buffer)); - bufptr += strlen(bufptr); - } - - return (buffer); - } - - /* - * Figure out the authentication data requirements to advertise... - */ - - if (p->type & CUPS_PRINTER_CLASS) - snprintf(resource, sizeof(resource), "/classes/%s", p->name); - else - snprintf(resource, sizeof(resource), "/printers/%s", p->name); - - if ((auth = cupsdFindBest(resource, HTTP_POST)) == NULL || - auth->type == CUPSD_AUTH_NONE) - auth = cupsdFindPolicyOp(p->op_policy_ptr, IPP_PRINT_JOB); - - if (auth) - { - int auth_type; /* Authentication type */ - - if ((auth_type = auth->type) == CUPSD_AUTH_DEFAULT) - auth_type = DefaultAuthType; - - switch (auth_type) - { - case CUPSD_AUTH_NONE : - return (NULL); - - case CUPSD_AUTH_NEGOTIATE : - strlcpy(buffer, "negotiate", bufsize); - break; - - default : - strlcpy(buffer, "username,password", bufsize); - break; - } - - return (buffer); - } - - return ("none"); -} - - -#ifdef __APPLE__ -/* - * 'get_hostconfig()' - Get an /etc/hostconfig service setting. - */ - -static int /* O - 1 for YES or AUTOMATIC, 0 for NO */ -get_hostconfig(const char *name) /* I - Name of service */ -{ - cups_file_t *fp; /* Hostconfig file */ - char line[1024], /* Line from file */ - *ptr; /* Pointer to value */ - int state = 1; /* State of service */ - - - /* - * Try opening the /etc/hostconfig file; if we can't open it, assume that - * the service is enabled/auto. - */ - - if ((fp = cupsFileOpen("/etc/hostconfig", "r")) != NULL) - { - /* - * Read lines from the file until we find the service... - */ - - while (cupsFileGets(fp, line, sizeof(line))) - { - if (line[0] == '#' || (ptr = strchr(line, '=')) == NULL) - continue; - - *ptr++ = '\0'; - - if (!_cups_strcasecmp(line, name)) - { - /* - * Found the service, see if it is set to "-NO-"... - */ - - if (!_cups_strncasecmp(ptr, "-NO-", 4)) - state = 0; - break; - } - } - - cupsFileClose(fp); - } - - return (state); -} -#endif /* __APPLE__ */ - - -/* - * 'is_local_queue()' - Determine whether the URI points at a local queue. - */ - -static int /* O - 1 = local, 0 = remote, -1 = bad URI */ -is_local_queue(const char *uri, /* I - Printer URI */ - char *host, /* O - Host string */ - int hostlen, /* I - Length of host buffer */ - char *resource, /* O - Resource string */ - int resourcelen) /* I - Length of resource buffer */ -{ - char scheme[32], /* Scheme portion of URI */ - username[HTTP_MAX_URI]; /* Username portion of URI */ - int port; /* Port portion of URI */ - cupsd_netif_t *iface; /* Network interface */ - - - /* - * Pull the URI apart to see if this is a local or remote printer... - */ - - if (httpSeparateURI(HTTP_URI_CODING_ALL, uri, scheme, sizeof(scheme), - username, sizeof(username), host, hostlen, &port, - resource, resourcelen) < HTTP_URI_OK) - return (-1); - - DEBUG_printf(("host=\"%s\", ServerName=\"%s\"\n", host, ServerName)); - - /* - * Check for local server addresses... - */ - - if (!_cups_strcasecmp(host, ServerName) && port == LocalPort) - return (1); - - cupsdNetIFUpdate(); - - for (iface = (cupsd_netif_t *)cupsArrayFirst(NetIFList); - iface; - iface = (cupsd_netif_t *)cupsArrayNext(NetIFList)) - if (!_cups_strcasecmp(host, iface->hostname) && port == iface->port) - return (1); - - /* - * If we get here, the printer is remote... - */ - - return (0); -} - - -/* - * 'process_browse_data()' - Process new browse data. - */ - -static void -process_browse_data( - const char *uri, /* I - URI of printer/class */ - const char *host, /* I - Hostname */ - const char *resource, /* I - Resource path */ - cups_ptype_t type, /* I - Printer type */ - ipp_pstate_t state, /* I - Printer state */ - const char *location, /* I - Printer location */ - const char *info, /* I - Printer information */ - const char *make_model, /* I - Printer make and model */ - int num_attrs, /* I - Number of attributes */ - cups_option_t *attrs) /* I - Attributes */ -{ - int i; /* Looping var */ - int update; /* Update printer attributes? */ - char finaluri[HTTP_MAX_URI], /* Final URI for printer */ - name[IPP_MAX_NAME], /* Name of printer */ - newname[IPP_MAX_NAME], /* New name of printer */ - *hptr, /* Pointer into hostname */ - *sptr; /* Pointer into ServerName */ - const char *shortname; /* Short queue name (queue) */ - char local_make_model[IPP_MAX_NAME]; - /* Local make and model */ - cupsd_printer_t *p; /* Printer information */ - const char *ipp_options, /* ipp-options value */ - *lease_duration, /* lease-duration value */ - *uuid; /* uuid value */ - int is_class; /* Is this queue a class? */ - - - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "process_browse_data(uri=\"%s\", host=\"%s\", " - "resource=\"%s\", type=%x, state=%d, location=\"%s\", " - "info=\"%s\", make_model=\"%s\", num_attrs=%d, attrs=%p)", - uri, host, resource, type, state, - location ? location : "(nil)", info ? info : "(nil)", - make_model ? make_model : "(nil)", num_attrs, attrs); - - /* - * Determine if the URI contains any illegal characters in it... - */ - - if (strncmp(uri, "ipp://", 6) || !host[0] || - (strncmp(resource, "/printers/", 10) && - strncmp(resource, "/classes/", 9))) - { - cupsdLogMessage(CUPSD_LOG_ERROR, "Bad printer URI in browse data: %s", uri); - return; - } - - if (strchr(resource, '?') || - (!strncmp(resource, "/printers/", 10) && strchr(resource + 10, '/')) || - (!strncmp(resource, "/classes/", 9) && strchr(resource + 9, '/'))) - { - cupsdLogMessage(CUPSD_LOG_ERROR, "Bad resource in browse data: %s", - resource); - return; - } - - /* - * OK, this isn't a local printer; add any remote options... - */ - - ipp_options = cupsGetOption("ipp-options", num_attrs, attrs); - - if (BrowseRemoteOptions) - { - if (BrowseRemoteOptions[0] == '?') - { - /* - * Override server-supplied options... - */ - - snprintf(finaluri, sizeof(finaluri), "%s%s", uri, BrowseRemoteOptions); - } - else if (ipp_options) - { - /* - * Combine the server and local options... - */ - - snprintf(finaluri, sizeof(finaluri), "%s?%s+%s", uri, ipp_options, - BrowseRemoteOptions); - } - else - { - /* - * Just use the local options... - */ - - snprintf(finaluri, sizeof(finaluri), "%s?%s", uri, BrowseRemoteOptions); - } - - uri = finaluri; - } - else if (ipp_options) - { - /* - * Just use the server-supplied options... - */ - - snprintf(finaluri, sizeof(finaluri), "%s?%s", uri, ipp_options); - uri = finaluri; - } - - /* - * See if we already have it listed in the Printers list, and add it if not... - */ - - type |= CUPS_PRINTER_REMOTE | CUPS_PRINTER_DISCOVERED; - type &= ~CUPS_PRINTER_IMPLICIT; - update = 0; - hptr = strchr(host, '.'); - sptr = strchr(ServerName, '.'); - is_class = type & CUPS_PRINTER_CLASS; - uuid = cupsGetOption("uuid", num_attrs, attrs); - - if (!ServerNameIsIP && sptr != NULL && hptr != NULL) - { - /* - * Strip the common domain name components... - */ - - while (hptr != NULL) - { - if (!_cups_strcasecmp(hptr, sptr)) - { - *hptr = '\0'; - break; - } - else - hptr = strchr(hptr + 1, '.'); - } - } - - if (is_class) - { - /* - * Remote destination is a class... - */ - - if (!strncmp(resource, "/classes/", 9)) - snprintf(name, sizeof(name), "%s@%s", resource + 9, host); - else - return; - - shortname = resource + 9; - } - else - { - /* - * Remote destination is a printer... - */ - - if (!strncmp(resource, "/printers/", 10)) - snprintf(name, sizeof(name), "%s@%s", resource + 10, host); - else - return; - - shortname = resource + 10; - } - - if (hptr && !*hptr) - *hptr = '.'; /* Resource FQDN */ - - if ((p = cupsdFindDest(name)) == NULL && BrowseShortNames) - { - /* - * Long name doesn't exist, try short name... - */ - - cupsdLogMessage(CUPSD_LOG_DEBUG, "process_browse_data: %s not found...", - name); - - if ((p = cupsdFindDest(shortname)) == NULL) - { - /* - * Short name doesn't exist, use it for this shared queue. - */ - - cupsdLogMessage(CUPSD_LOG_DEBUG2, "process_browse_data: %s not found...", - shortname); - strlcpy(name, shortname, sizeof(name)); - } - else - { - /* - * Short name exists... - */ - - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "process_browse_data: %s found, type=%x, hostname=%s...", - shortname, p->type, p->hostname ? p->hostname : "(nil)"); - - if (p->type & CUPS_PRINTER_IMPLICIT) - p = NULL; /* Don't replace implicit classes */ - else if (p->hostname && _cups_strcasecmp(p->hostname, host)) - { - /* - * Short name exists but is for a different host. If this is a remote - * queue, rename it and use the long name... - */ - - if (p->type & CUPS_PRINTER_REMOTE) - { - cupsdLogMessage(CUPSD_LOG_DEBUG, - "Renamed remote %s \"%s\" to \"%s@%s\"...", - is_class ? "class" : "printer", p->name, p->name, - p->hostname); - cupsdAddEvent(CUPSD_EVENT_PRINTER_DELETED, p, NULL, - "%s \'%s\' deleted by directory services.", - is_class ? "Class" : "Printer", p->name); - - snprintf(newname, sizeof(newname), "%s@%s", p->name, p->hostname); - cupsdRenamePrinter(p, newname); - - cupsdAddEvent(CUPSD_EVENT_PRINTER_ADDED, p, NULL, - "%s \'%s\' added by directory services.", - is_class ? "Class" : "Printer", p->name); - } - - /* - * Force creation with long name... - */ - - p = NULL; - } - } - } - else if (p) - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "process_browse_data: %s found, type=%x, hostname=%s...", - name, p->type, p->hostname ? p->hostname : "(nil)"); - - if (!p) - { - /* - * Queue doesn't exist; add it... - */ - - if (is_class) - p = cupsdAddClass(name); - else - p = cupsdAddPrinter(name); - - if (!p) - return; - - cupsdClearString(&(p->hostname)); - - cupsdLogMessage(CUPSD_LOG_DEBUG, "Added remote %s \"%s\"...", - is_class ? "class" : "printer", name); - - cupsdAddEvent(CUPSD_EVENT_PRINTER_ADDED, p, NULL, - "%s \'%s\' added by directory services.", - is_class ? "Class" : "Printer", name); - - /* - * Force the URI to point to the real server... - */ - - p->type = type & ~CUPS_PRINTER_REJECTING; - p->accepting = 1; - - cupsdMarkDirty(CUPSD_DIRTY_PRINTCAP); - } - - if (!p->hostname) - { - /* - * Hostname not set, so this must be a cached remote printer - * that was created for a pending print job... - */ - - cupsdSetString(&p->hostname, host); - cupsdSetString(&p->uri, uri); - cupsdSetString(&p->device_uri, uri); - update = 1; - - cupsdMarkDirty(CUPSD_DIRTY_REMOTE); - } - - /* - * Update the state... - */ - - p->state = state; - p->browse_time = time(NULL); - - if ((lease_duration = cupsGetOption("lease-duration", num_attrs, - attrs)) != NULL) - { - /* - * Grab the lease-duration for the browse data; anything less then 1 - * second or more than 1 week gets the default BrowseTimeout... - */ - - i = atoi(lease_duration); - if (i < 1 || i > 604800) - i = BrowseTimeout; - - p->browse_expire = p->browse_time + i; - } - else - p->browse_expire = p->browse_time + BrowseTimeout; - - if (type & CUPS_PRINTER_REJECTING) - { - type &= ~CUPS_PRINTER_REJECTING; - - if (p->accepting) - { - update = 1; - p->accepting = 0; - } - } - else if (!p->accepting) - { - update = 1; - p->accepting = 1; - } - - if (p->type != type) - { - p->type = type; - update = 1; - } - - if (uuid && strcmp(p->uuid, uuid)) - { - cupsdSetString(&p->uuid, uuid); - update = 1; - } - - if (location && (!p->location || strcmp(p->location, location))) - { - cupsdSetString(&p->location, location); - update = 1; - } - - if (info && (!p->info || strcmp(p->info, info))) - { - cupsdSetString(&p->info, info); - update = 1; - - cupsdMarkDirty(CUPSD_DIRTY_PRINTCAP | CUPSD_DIRTY_REMOTE); - } - - if (!make_model || !make_model[0]) - { - if (is_class) - snprintf(local_make_model, sizeof(local_make_model), - "Remote Class on %s", host); - else - snprintf(local_make_model, sizeof(local_make_model), - "Remote Printer on %s", host); - } - else - snprintf(local_make_model, sizeof(local_make_model), - "%s on %s", make_model, host); - - if (!p->make_model || strcmp(p->make_model, local_make_model)) - { - cupsdSetString(&p->make_model, local_make_model); - update = 1; - } - - if (p->num_options) - { - if (!update && !(type & CUPS_PRINTER_DELETE)) - { - /* - * See if we need to update the attributes... - */ - - if (p->num_options != num_attrs) - update = 1; - else - { - for (i = 0; i < num_attrs; i ++) - if (strcmp(attrs[i].name, p->options[i].name) || - (!attrs[i].value != !p->options[i].value) || - (attrs[i].value && strcmp(attrs[i].value, p->options[i].value))) - { - update = 1; - break; - } - } - } - - /* - * Free the old options... - */ - - cupsFreeOptions(p->num_options, p->options); - } - - p->num_options = num_attrs; - p->options = attrs; - - if (type & CUPS_PRINTER_DELETE) - { - cupsdAddEvent(CUPSD_EVENT_PRINTER_DELETED, p, NULL, - "%s \'%s\' deleted by directory services.", - is_class ? "Class" : "Printer", p->name); - - cupsdExpireSubscriptions(p, NULL); - - cupsdDeletePrinter(p, 1); - cupsdUpdateImplicitClasses(); - cupsdMarkDirty(CUPSD_DIRTY_PRINTCAP | CUPSD_DIRTY_REMOTE); - } - else if (update) - { - cupsdSetPrinterAttrs(p); - cupsdUpdateImplicitClasses(); - } - - /* - * See if we have a default printer... If not, make the first network - * default printer the default. - */ - - if (DefaultPrinter == NULL && Printers != NULL && UseNetworkDefault) - { - /* - * Find the first network default printer and use it... - */ - - for (p = (cupsd_printer_t *)cupsArrayFirst(Printers); - p; - p = (cupsd_printer_t *)cupsArrayNext(Printers)) - if (p->type & CUPS_PRINTER_DEFAULT) - { - DefaultPrinter = p; - cupsdMarkDirty(CUPSD_DIRTY_PRINTCAP | CUPSD_DIRTY_REMOTE); - break; - } - } - - /* - * Do auto-classing if needed... - */ - - process_implicit_classes(); -} - - -/* - * 'process_implicit_classes()' - Create/update implicit classes as needed. - */ - -static void -process_implicit_classes(void) +static char * /* O - TXT record */ +dnssdBuildTxtRecord( + int *txt_len, /* O - TXT record length */ + cupsd_printer_t *p, /* I - Printer information */ + int for_lpd) /* I - 1 = LPD, 0 = IPP */ { int i; /* Looping var */ - int update; /* Update printer attributes? */ - char name[IPP_MAX_NAME], /* Name of printer */ - *hptr; /* Pointer into hostname */ - cupsd_printer_t *p, /* Printer information */ - *pclass, /* Printer class */ - *first; /* First printer in class */ - int offset, /* Offset of name */ - len; /* Length of name */ - - - if (!ImplicitClasses || !Printers) - return; - - /* - * Loop through all available printers and create classes as needed... - */ - - for (p = (cupsd_printer_t *)cupsArrayFirst(Printers), len = 0, offset = 0, - update = 0, pclass = NULL, first = NULL; - p != NULL; - p = (cupsd_printer_t *)cupsArrayNext(Printers)) - { - /* - * Skip implicit classes... - */ - - if (p->type & CUPS_PRINTER_IMPLICIT) - { - len = 0; - continue; - } - - /* - * If len == 0, get the length of this printer name up to the "@" - * sign (if any). - */ - - cupsArraySave(Printers); - - if (len > 0 && - !_cups_strncasecmp(p->name, name + offset, len) && - (p->name[len] == '\0' || p->name[len] == '@')) - { - /* - * We have more than one printer with the same name; see if - * we have a class, and if this printer is a member... - */ - - if (pclass && _cups_strcasecmp(pclass->name, name)) - { - if (update) - cupsdSetPrinterAttrs(pclass); - - update = 0; - pclass = NULL; - } - - if (!pclass && (pclass = cupsdFindDest(name)) == NULL) - { - /* - * Need to add the class... - */ - - pclass = cupsdAddPrinter(name); - cupsArrayAdd(ImplicitPrinters, pclass); - - pclass->type |= CUPS_PRINTER_IMPLICIT; - pclass->accepting = 1; - pclass->state = IPP_PRINTER_IDLE; - - cupsdSetString(&pclass->location, p->location); - cupsdSetString(&pclass->info, p->info); - - cupsdSetString(&pclass->job_sheets[0], p->job_sheets[0]); - cupsdSetString(&pclass->job_sheets[1], p->job_sheets[1]); - - update = 1; - - cupsdMarkDirty(CUPSD_DIRTY_PRINTCAP | CUPSD_DIRTY_REMOTE); - - cupsdLogMessage(CUPSD_LOG_DEBUG, "Added implicit class \"%s\"...", - name); - cupsdAddEvent(CUPSD_EVENT_PRINTER_ADDED, p, NULL, - "Implicit class \'%s\' added by directory services.", - name); - } - - if (first != NULL) - { - for (i = 0; i < pclass->num_printers; i ++) - if (pclass->printers[i] == first) - break; - - if (i >= pclass->num_printers) - { - first->in_implicit_class = 1; - cupsdAddPrinterToClass(pclass, first); - } - - first = NULL; - } - - for (i = 0; i < pclass->num_printers; i ++) - if (pclass->printers[i] == p) - break; - - if (i >= pclass->num_printers) - { - p->in_implicit_class = 1; - cupsdAddPrinterToClass(pclass, p); - update = 1; - } - } - else - { - /* - * First time around; just get name length and mark it as first - * in the list... - */ - - if ((hptr = strchr(p->name, '@')) != NULL) - len = hptr - p->name; - else - len = strlen(p->name); - - if (len >= sizeof(name)) - { - /* - * If the printer name length somehow is greater than we normally allow, - * skip this printer... - */ - - len = 0; - cupsArrayRestore(Printers); - continue; - } - - strncpy(name, p->name, len); - name[len] = '\0'; - offset = 0; - - if ((first = (hptr ? cupsdFindDest(name) : p)) != NULL && - !(first->type & CUPS_PRINTER_IMPLICIT)) - { - /* - * Can't use same name as a local printer; add "Any" to the - * front of the name, unless we have explicitly disabled - * the "ImplicitAnyClasses"... - */ - - if (ImplicitAnyClasses && len < (sizeof(name) - 4)) - { - /* - * Add "Any" to the class name... - */ - - strcpy(name, "Any"); - strncpy(name + 3, p->name, len); - name[len + 3] = '\0'; - offset = 3; - } - else - { - /* - * Don't create an implicit class if we have a local printer - * with the same name... - */ - - len = 0; - cupsArrayRestore(Printers); - continue; - } - } - - first = p; - } - - cupsArrayRestore(Printers); - } - - /* - * Update the last printer class as needed... - */ - - if (pclass && update) - cupsdSetPrinterAttrs(pclass); -} - - -/* - * 'send_cups_browse()' - Send new browsing information using the CUPS - * protocol. - */ - -static void -send_cups_browse(cupsd_printer_t *p) /* I - Printer to send */ -{ - int i; /* Looping var */ - cups_ptype_t type; /* Printer type */ - cupsd_dirsvc_addr_t *b; /* Browse address */ - int bytes; /* Length of packet */ - char packet[1453], /* Browse data packet */ - uri[1024], /* Printer URI */ - location[1024], /* printer-location */ - info[1024], /* printer-info */ - make_model[1024], - /* printer-make-and-model */ - air[1024]; /* auth-info-required */ - cupsd_netif_t *iface; /* Network interface */ - - - /* - * Figure out the printer type value... - */ - - type = p->type | CUPS_PRINTER_REMOTE; - - if (!p->accepting) - type |= CUPS_PRINTER_REJECTING; - - if (p == DefaultPrinter) - type |= CUPS_PRINTER_DEFAULT; - - /* - * Remove quotes from printer-info, printer-location, and - * printer-make-and-model attributes... - */ - - dequote(location, p->location, sizeof(location)); - dequote(info, p->info, sizeof(info)); - - if (p->make_model) - dequote(make_model, p->make_model, sizeof(make_model)); - else if (p->type & CUPS_PRINTER_CLASS) - { - if (p->num_printers > 0 && p->printers[0]->make_model) - strlcpy(make_model, p->printers[0]->make_model, sizeof(make_model)); - else - strlcpy(make_model, "Local Printer Class", sizeof(make_model)); - } - else if (p->raw) - strlcpy(make_model, "Local Raw Printer", sizeof(make_model)); - else - strlcpy(make_model, "Local System V Printer", sizeof(make_model)); - - if (get_auth_info_required(p, packet, sizeof(packet))) - snprintf(air, sizeof(air), " auth-info-required=%s", packet); - else - air[0] = '\0'; - - /* - * Send a packet to each browse address... - */ - - for (i = NumBrowsers, b = Browsers; i > 0; i --, b ++) - if (b->iface[0]) - { - /* - * Send the browse packet to one or more interfaces... - */ - - if (!strcmp(b->iface, "*")) - { - /* - * Send to all local interfaces... - */ - - cupsdNetIFUpdate(); - - for (iface = (cupsd_netif_t *)cupsArrayFirst(NetIFList); - iface; - iface = (cupsd_netif_t *)cupsArrayNext(NetIFList)) - { - /* - * Only send to local, IPv4 interfaces... - */ - - if (!iface->is_local || !iface->port || - iface->address.addr.sa_family != AF_INET) - continue; - - httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL, - iface->hostname, iface->port, - (p->type & CUPS_PRINTER_CLASS) ? "/classes/%s" : - "/printers/%s", - p->name); - snprintf(packet, sizeof(packet), - "%x %x %s \"%s\" \"%s\" \"%s\" %s%s uuid=%s\n", - type, p->state, uri, location, info, make_model, - p->browse_attrs ? p->browse_attrs : "", air, p->uuid); - - bytes = strlen(packet); - - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "cupsdSendBrowseList: (%d bytes to \"%s\") %s", bytes, - iface->name, packet); - - iface->broadcast.ipv4.sin_port = htons(BrowsePort); - - sendto(BrowseSocket, packet, bytes, 0, - (struct sockaddr *)&(iface->broadcast), - httpAddrLength(&(iface->broadcast))); - } - } - else if ((iface = cupsdNetIFFind(b->iface)) != NULL) - { - /* - * Send to the named interface using the IPv4 address... - */ - - while (iface) - if (strcmp(b->iface, iface->name)) - { - iface = NULL; - break; - } - else if (iface->address.addr.sa_family == AF_INET && iface->port) - break; - else - iface = (cupsd_netif_t *)cupsArrayNext(NetIFList); - - if (iface) - { - httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL, - iface->hostname, iface->port, - (p->type & CUPS_PRINTER_CLASS) ? "/classes/%s" : - "/printers/%s", - p->name); - snprintf(packet, sizeof(packet), - "%x %x %s \"%s\" \"%s\" \"%s\" %s%s uuid=%s\n", - type, p->state, uri, location, info, make_model, - p->browse_attrs ? p->browse_attrs : "", air, p->uuid); - - bytes = strlen(packet); - - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "cupsdSendBrowseList: (%d bytes to \"%s\") %s", bytes, - iface->name, packet); - - iface->broadcast.ipv4.sin_port = htons(BrowsePort); - - sendto(BrowseSocket, packet, bytes, 0, - (struct sockaddr *)&(iface->broadcast), - httpAddrLength(&(iface->broadcast))); - } - } - } - else - { - /* - * Send the browse packet to the indicated address using - * the default server name... - */ - - snprintf(packet, sizeof(packet), - "%x %x %s \"%s\" \"%s\" \"%s\" %s%s uuid=%s\n", - type, p->state, p->uri, location, info, make_model, - p->browse_attrs ? p->browse_attrs : "", air, p->uuid); - - bytes = strlen(packet); - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "cupsdSendBrowseList: (%d bytes) %s", bytes, packet); - - if (sendto(BrowseSocket, packet, bytes, 0, - (struct sockaddr *)&(b->to), - httpAddrLength(&(b->to))) <= 0) - { - /* - * Unable to send browse packet, so remove this address from the - * list... - */ - - cupsdLogMessage(CUPSD_LOG_ERROR, - "cupsdSendBrowseList: sendto failed for browser " - "%d - %s.", - (int)(b - Browsers + 1), strerror(errno)); - - if (i > 1) - memmove(b, b + 1, (i - 1) * sizeof(cupsd_dirsvc_addr_t)); - - b --; - NumBrowsers --; - } - } -} - - -#ifdef HAVE_LDAP -/* - * 'ldap_search_rec()' - LDAP Search with reconnect - */ - -static int /* O - Return code */ -ldap_search_rec(LDAP *ld, /* I - LDAP handler */ - char *base, /* I - Base dn */ - int scope, /* I - LDAP search scope */ - char *filter, /* I - Filter string */ - char *attrs[], /* I - Requested attributes */ - int attrsonly, /* I - Return only attributes? */ - LDAPMessage **res) /* I - LDAP handler */ -{ - int rc; /* Return code */ - LDAP *ldr; /* LDAP handler after reconnect */ - - -# if defined(HAVE_OPENLDAP) && LDAP_API_VERSION > 3000 - rc = ldap_search_ext_s(ld, base, scope, filter, attrs, attrsonly, NULL, NULL, - NULL, LDAP_NO_LIMIT, res); -# else - rc = ldap_search_s(ld, base, scope, filter, attrs, attrsonly, res); -# endif /* defined(HAVE_OPENLDAP) && LDAP_API_VERSION > 3000 */ - - /* - * If we have a connection problem try again... - */ - - if (rc == LDAP_SERVER_DOWN || rc == LDAP_CONNECT_ERROR) - { - cupsdLogMessage(CUPSD_LOG_ERROR, - "LDAP search failed with status %d: %s", - rc, ldap_err2string(rc)); - cupsdLogMessage(CUPSD_LOG_INFO, - "We try the LDAP search once again after reconnecting to " - "the server"); - ldap_freeres(*res); - ldr = ldap_reconnect(); - -# if defined(HAVE_OPENLDAP) && LDAP_API_VERSION > 3000 - rc = ldap_search_ext_s(ldr, base, scope, filter, attrs, attrsonly, NULL, - NULL, NULL, LDAP_NO_LIMIT, res); -# else - rc = ldap_search_s(ldr, base, scope, filter, attrs, attrsonly, res); -# endif /* defined(HAVE_OPENLDAP) && LDAP_API_VERSION > 3000 */ - } - - if (rc == LDAP_NO_SUCH_OBJECT) - cupsdLogMessage(CUPSD_LOG_DEBUG, - "ldap_search_rec: LDAP entry/object not found"); - else if (rc != LDAP_SUCCESS) - cupsdLogMessage(CUPSD_LOG_ERROR, - "ldap_search_rec: LDAP search failed with status %d: %s", - rc, ldap_err2string(rc)); - - if (rc != LDAP_SUCCESS) - ldap_freeres(*res); - - return (rc); -} - - -/* - * 'ldap_freeres()' - Free LDAPMessage - */ - -static void -ldap_freeres(LDAPMessage *entry) /* I - LDAP handler */ -{ - int rc; /* Return value */ - - - rc = ldap_msgfree(entry); - if (rc == -1) - cupsdLogMessage(CUPSD_LOG_WARN, "Can't free LDAPMessage!"); - else if (rc == 0) - cupsdLogMessage(CUPSD_LOG_DEBUG2, "Freeing LDAPMessage was unnecessary"); -} - - -/* - * 'ldap_getval_char()' - Get first LDAP value and convert to string - */ - -static int /* O - Return code */ -ldap_getval_firststring( - LDAP *ld, /* I - LDAP handler */ - LDAPMessage *entry, /* I - LDAP message or search result */ - char *attr, /* I - the wanted attribute */ - char *retval, /* O - String to return */ - unsigned long maxsize) /* I - Max string size */ -{ - char *dn; /* LDAP DN */ - int rc = 0; /* Return code */ -# if defined(HAVE_OPENLDAP) && LDAP_API_VERSION > 3000 - struct berval **bval; /* LDAP value array */ - unsigned long size; /* String size */ - - - /* - * Get value from LDAPMessage... - */ - - if ((bval = ldap_get_values_len(ld, entry, attr)) == NULL) - { - rc = -1; - dn = ldap_get_dn(ld, entry); - cupsdLogMessage(CUPSD_LOG_WARN, - "Failed to get LDAP value %s for %s!", - attr, dn); - ldap_memfree(dn); - } - else - { - /* - * Check size and copy value into our string... - */ - - size = maxsize; - if (size < (bval[0]->bv_len + 1)) - { - rc = -1; - dn = ldap_get_dn(ld, entry); - cupsdLogMessage(CUPSD_LOG_WARN, - "Attribute %s is too big! (dn: %s)", - attr, dn); - ldap_memfree(dn); - } - else - size = bval[0]->bv_len + 1; - - strlcpy(retval, bval[0]->bv_val, size); - ldap_value_free_len(bval); - } -# else - char **value; /* LDAP value */ - - /* - * Get value from LDAPMessage... - */ - - if ((value = (char **)ldap_get_values(ld, entry, attr)) == NULL) - { - rc = -1; - dn = ldap_get_dn(ld, entry); - cupsdLogMessage(CUPSD_LOG_WARN, "Failed to get LDAP value %s for %s!", - attr, dn); - ldap_memfree(dn); - } - else - { - strlcpy(retval, *value, maxsize); - ldap_value_free(value); - } -# endif /* defined(HAVE_OPENLDAP) && LDAP_API_VERSION > 3000 */ - - return (rc); -} - - -/* - * 'send_ldap_ou()' - Send LDAP ou registrations. - */ + char admin_hostname[256], /* .local hostname for admin page */ + adminurl_str[256], /* URL for the admin page */ + type_str[32], /* Type to string buffer */ + state_str[32], /* State to string buffer */ + rp_str[1024], /* Queue name string buffer */ + air_str[1024], /* auth-info-required string buffer */ + *keyvalue[32][2]; /* Table of key/value pairs */ -static void -send_ldap_ou(char *ou, /* I - Servername/ou to register */ - char *basedn, /* I - Our base dn */ - char *descstring) /* I - Description for ou */ -{ - int i; /* Looping var... */ - LDAPMod mods[3]; /* The 3 attributes we will be adding */ - LDAPMod *pmods[4]; /* Pointers to the 3 attributes + NULL */ - LDAPMessage *res, /* Search result token */ - *e; /* Current entry from search */ - int rc; /* LDAP status */ - int rcmod; /* LDAP status for modifications */ - char dn[1024], /* DN of the organizational unit we are adding */ - *desc[2], /* Change records */ - *ou_value[2]; - char old_desc[1024]; /* Old description */ - static const char * const objectClass_values[] = - { /* The 2 objectClass's we use in */ - "top", /* our LDAP entries */ - "organizationalUnit", - NULL - }; - static const char * const ou_attrs[] =/* CUPS LDAP attributes */ - { - "description", - NULL - }; - - - cupsdLogMessage(CUPSD_LOG_DEBUG2, "send_ldap_ou: %s", ou); /* - * Reconnect if LDAP Handle is invalid... + * Load up the key value pairs... */ - if (!BrowseLDAPHandle) - { - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "send_ldap_ou: LDAP Handle is invalid. Try reconnecting..."); - ldap_reconnect(); - return; - } + i = 0; - /* - * Prepare ldap search... - */ + keyvalue[i ][0] = "txtvers"; + keyvalue[i++][1] = "1"; - snprintf(dn, sizeof(dn), "ou=%s, %s", ou, basedn); - cupsdLogMessage(CUPSD_LOG_DEBUG2, "send_ldap_ou: dn=\"%s\"", dn); + keyvalue[i ][0] = "qtotal"; + keyvalue[i++][1] = "1"; - ou_value[0] = ou; - ou_value[1] = NULL; - desc[0] = descstring; - desc[1] = NULL; + keyvalue[i ][0] = "rp"; + keyvalue[i++][1] = rp_str; + if (for_lpd) + strlcpy(rp_str, p->name, sizeof(rp_str)); + else + snprintf(rp_str, sizeof(rp_str), "%s/%s", + (p->type & CUPS_PRINTER_CLASS) ? "classes" : "printers", p->name); - mods[0].mod_type = "ou"; - mods[0].mod_values = ou_value; - mods[1].mod_type = "description"; - mods[1].mod_values = desc; - mods[2].mod_type = "objectClass"; - mods[2].mod_values = (char **)objectClass_values; + keyvalue[i ][0] = "ty"; + keyvalue[i++][1] = p->make_model ? p->make_model : "Unknown"; - rc = ldap_search_rec(BrowseLDAPHandle, dn, LDAP_SCOPE_BASE, NULL, - (char **)ou_attrs, 0, &res); + snprintf(admin_hostname, sizeof(admin_hostname), "%s.local.", DNSSDHostName); + httpAssembleURIf(HTTP_URI_CODING_ALL, adminurl_str, sizeof(adminurl_str), + "http", NULL, admin_hostname, DNSSDPort, "/%s/%s", + (p->type & CUPS_PRINTER_CLASS) ? "classes" : "printers", + p->name); + keyvalue[i ][0] = "adminurl"; + keyvalue[i++][1] = adminurl_str; - /* - * If ldap search was not successfull then exit function... - */ + keyvalue[i ][0] = "note"; + keyvalue[i++][1] = p->location ? p->location : ""; - if (rc != LDAP_SUCCESS && rc != LDAP_NO_SUCH_OBJECT) - return; + keyvalue[i ][0] = "priority"; + keyvalue[i++][1] = for_lpd ? "100" : "0"; - /* - * Check if we need to insert or update the LDAP entry... - */ + keyvalue[i ][0] = "product"; + keyvalue[i++][1] = p->pc && p->pc->product ? p->pc->product : "Unknown"; - if (ldap_count_entries(BrowseLDAPHandle, res) > 0 && - rc != LDAP_NO_SUCH_OBJECT) + keyvalue[i ][0] = "pdl"; + keyvalue[i++][1] = p->pdl ? p->pdl : "application/postscript"; + + if (get_auth_info_required(p, air_str, sizeof(air_str))) { - /* - * Printserver has already been registered, check if - * modification is required... - */ + keyvalue[i ][0] = "air"; + keyvalue[i++][1] = air_str; + } - e = ldap_first_entry(BrowseLDAPHandle, res); + keyvalue[i ][0] = "UUID"; + keyvalue[i++][1] = p->uuid + 9; - /* - * Get the required values from this entry... - */ +#ifdef HAVE_SSL + keyvalue[i ][0] = "TLS"; + keyvalue[i++][1] = "1.2"; +#endif /* HAVE_SSL */ - if (ldap_getval_firststring(BrowseLDAPHandle, e, "description", old_desc, - sizeof(old_desc)) == -1) - old_desc[0] = '\0'; + keyvalue[i ][0] = "Transparent"; + keyvalue[i++][1] = "F"; - /* - * Check if modification is required... - */ + keyvalue[i ][0] = "Binary"; + keyvalue[i++][1] = "F"; - if ( strcmp(desc[0], old_desc) == 0 ) - { - /* - * LDAP entry for the printer exists. - * Printer has already been registered, - * no modifications required... - */ - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "send_ldap_ou: No updates required for %s", ou); - } - else - { + keyvalue[i ][0] = "Fax"; + keyvalue[i++][1] = (p->type & CUPS_PRINTER_FAX) ? "T" : "F"; - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "send_ldap_ou: Replace entry for %s", ou); + keyvalue[i ][0] = "Color"; + keyvalue[i++][1] = (p->type & CUPS_PRINTER_COLOR) ? "T" : "F"; - for (i = 0; i < 3; i ++) - { - pmods[i] = mods + i; - pmods[i]->mod_op = LDAP_MOD_REPLACE; - } - pmods[i] = NULL; - -# if defined(HAVE_OPENLDAP) && LDAP_API_VERSION > 3000 - if ((rcmod = ldap_modify_ext_s(BrowseLDAPHandle, dn, pmods, NULL, - NULL)) != LDAP_SUCCESS) -# else - if ((rcmod = ldap_modify_s(BrowseLDAPHandle, dn, pmods)) != LDAP_SUCCESS) -# endif /* defined(HAVE_OPENLDAP) && LDAP_API_VERSION > 3000 */ - { - cupsdLogMessage(CUPSD_LOG_ERROR, - "LDAP modify for %s failed with status %d: %s", - ou, rcmod, ldap_err2string(rcmod)); - if (rcmod == LDAP_SERVER_DOWN) - ldap_reconnect(); - } - } - } - else - { - /* - * Printserver has never been registered, - * add registration... - */ + keyvalue[i ][0] = "Duplex"; + keyvalue[i++][1] = (p->type & CUPS_PRINTER_DUPLEX) ? "T" : "F"; - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "send_ldap_ou: Add entry for %s", ou); + keyvalue[i ][0] = "Staple"; + keyvalue[i++][1] = (p->type & CUPS_PRINTER_STAPLE) ? "T" : "F"; - for (i = 0; i < 3; i ++) - { - pmods[i] = mods + i; - pmods[i]->mod_op = LDAP_MOD_ADD; - } - pmods[i] = NULL; - -# if defined(HAVE_OPENLDAP) && LDAP_API_VERSION > 3000 - if ((rcmod = ldap_add_ext_s(BrowseLDAPHandle, dn, pmods, NULL, - NULL)) != LDAP_SUCCESS) -# else - if ((rcmod = ldap_add_s(BrowseLDAPHandle, dn, pmods)) != LDAP_SUCCESS) -# endif /* defined(HAVE_OPENLDAP) && LDAP_API_VERSION > 3000 */ - { - cupsdLogMessage(CUPSD_LOG_ERROR, - "LDAP add for %s failed with status %d: %s", - ou, rcmod, ldap_err2string(rcmod)); - if (rcmod == LDAP_SERVER_DOWN) - ldap_reconnect(); - } - } + keyvalue[i ][0] = "Copies"; + keyvalue[i++][1] = (p->type & CUPS_PRINTER_COPIES) ? "T" : "F"; - if (rc == LDAP_SUCCESS) - ldap_freeres(res); -} + keyvalue[i ][0] = "Collate"; + keyvalue[i++][1] = (p->type & CUPS_PRINTER_COLLATE) ? "T" : "F"; + keyvalue[i ][0] = "Punch"; + keyvalue[i++][1] = (p->type & CUPS_PRINTER_PUNCH) ? "T" : "F"; -/* - * 'send_ldap_browse()' - Send LDAP printer registrations. - */ + keyvalue[i ][0] = "Bind"; + keyvalue[i++][1] = (p->type & CUPS_PRINTER_BIND) ? "T" : "F"; -static void -send_ldap_browse(cupsd_printer_t *p) /* I - Printer to register */ -{ - int i; /* Looping var... */ - LDAPMod mods[7]; /* The 7 attributes we will be adding */ - LDAPMod *pmods[8]; /* Pointers to the 7 attributes + NULL */ - LDAPMessage *res, /* Search result token */ - *e; /* Current entry from search */ - char *cn_value[2], /* Change records */ - *uri[2], - *info[2], - *location[2], - *make_model[2], - *type[2], - typestring[255], /* String to hold printer-type */ - dn[1024]; /* DN of the printer we are adding */ - int rc; /* LDAP status */ - int rcmod; /* LDAP status for modifications */ - char old_uri[HTTP_MAX_URI], /* Printer URI */ - old_location[1024], /* Printer location */ - old_info[1024], /* Printer information */ - old_make_model[1024], /* Printer make and model */ - old_type_string[30]; /* Temporary type number */ - int old_type; /* Printer type */ - static const char * const objectClass_values[] = - { /* The 3 objectClass's we use in */ - "top", /* our LDAP entries */ - "device", - "cupsPrinter", - NULL - }; - - - cupsdLogMessage(CUPSD_LOG_DEBUG2, "send_ldap_browse: %s", p->name); + keyvalue[i ][0] = "Sort"; + keyvalue[i++][1] = (p->type & CUPS_PRINTER_SORT) ? "T" : "F"; - /* - * Exit function if LDAP updates has been disabled... - */ + keyvalue[i ][0] = "Scan"; + keyvalue[i++][1] = (p->type & CUPS_PRINTER_MFP) ? "T" : "F"; - if (!BrowseLDAPUpdate) - { - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "send_ldap_browse: Updates temporary disabled; " - "skipping..."); - return; - } + snprintf(type_str, sizeof(type_str), "0x%X", p->type | CUPS_PRINTER_REMOTE); + snprintf(state_str, sizeof(state_str), "%d", p->state); - /* - * Reconnect if LDAP Handle is invalid... - */ + keyvalue[i ][0] = "printer-state"; + keyvalue[i++][1] = state_str; - if (!BrowseLDAPHandle) - { - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "send_ldap_browse: LDAP Handle is invalid. Try " - "reconnecting..."); - ldap_reconnect(); - return; - } + keyvalue[i ][0] = "printer-type"; + keyvalue[i++][1] = type_str; /* - * Everything in ldap is ** so we fudge around it... + * Then pack them into a proper txt record... */ - sprintf(typestring, "%u", p->type); - - cn_value[0] = p->name; - cn_value[1] = NULL; - info[0] = p->info ? p->info : "Unknown"; - info[1] = NULL; - location[0] = p->location ? p->location : "Unknown"; - location[1] = NULL; - make_model[0] = p->make_model ? p->make_model : "Unknown"; - make_model[1] = NULL; - type[0] = typestring; - type[1] = NULL; - uri[0] = p->uri; - uri[1] = NULL; + return (dnssdPackTxtRecord(txt_len, keyvalue, i)); +} - /* - * Get ldap entry for printer ... - */ - snprintf(dn, sizeof(dn), "cn=%s, ou=%s, %s", p->name, ServerName, - BrowseLDAPDN); - cupsdLogMessage(CUPSD_LOG_DEBUG2, "send_ldap_browse: dn=\"%s\"", dn); +/* + * 'dnssdDeregisterPrinter()' - Stop sending broadcast information for a + * printer. + */ - rc = ldap_search_rec(BrowseLDAPHandle, dn, LDAP_SCOPE_BASE, NULL, - (char **)ldap_attrs, 0, &res); +static void +dnssdDeregisterPrinter( + cupsd_printer_t *p) /* I - Printer */ +{ + cupsdLogMessage(CUPSD_LOG_DEBUG2, "dnssdDeregisterPrinter(%s)", p->name); /* - * If ldap search was not successfull then exit function - * and temporary disable LDAP updates... + * Closing the socket deregisters the service */ - if (rc != LDAP_SUCCESS && rc != LDAP_NO_SUCH_OBJECT) + if (p->ipp_ref) { - if (BrowseLDAPUpdate && - (rc == LDAP_SERVER_DOWN || rc == LDAP_CONNECT_ERROR)) - { - BrowseLDAPUpdate = FALSE; - cupsdLogMessage(CUPSD_LOG_INFO, - "LDAP update temporary disabled"); - } - - return; + DNSServiceRefDeallocate(p->ipp_ref); + p->ipp_ref = NULL; } - /* - * Fill modification array... - */ - - mods[0].mod_type = "cn"; - mods[0].mod_values = cn_value; - mods[1].mod_type = "printerDescription"; - mods[1].mod_values = info; - mods[2].mod_type = "printerURI"; - mods[2].mod_values = uri; - mods[3].mod_type = "printerLocation"; - mods[3].mod_values = location; - mods[4].mod_type = "printerMakeAndModel"; - mods[4].mod_values = make_model; - mods[5].mod_type = "printerType"; - mods[5].mod_values = type; - mods[6].mod_type = "objectClass"; - mods[6].mod_values = (char **)objectClass_values; - - /* - * Check if we need to insert or update the LDAP entry... - */ - - if (ldap_count_entries(BrowseLDAPHandle, res) > 0 && - rc != LDAP_NO_SUCH_OBJECT) + if (p->ipp_txt) { /* - * Printer has already been registered, check if - * modification is required... - */ - - e = ldap_first_entry(BrowseLDAPHandle, res); - - /* - * Get the required values from this entry... - */ - - if (ldap_getval_firststring(BrowseLDAPHandle, e, "printerDescription", - old_info, sizeof(old_info)) == -1) - old_info[0] = '\0'; - - if (ldap_getval_firststring(BrowseLDAPHandle, e, "printerLocation", - old_location, sizeof(old_location)) == -1) - old_info[0] = '\0'; - - if (ldap_getval_firststring(BrowseLDAPHandle, e, "printerMakeAndModel", - old_make_model, sizeof(old_make_model)) == -1) - old_info[0] = '\0'; - - if (ldap_getval_firststring(BrowseLDAPHandle, e, "printerType", - old_type_string, sizeof(old_type_string)) == -1) - old_info[0] = '\0'; - - old_type = atoi(old_type_string); - - if (ldap_getval_firststring(BrowseLDAPHandle, e, "printerURI", old_uri, - sizeof(old_uri)) == -1) - old_info[0] = '\0'; - - /* - * Check if modification is required... + * p->ipp_txt is malloc'd, not _cupsStrAlloc'd... */ - if (!strcmp(info[0], old_info) && !strcmp(uri[0], old_uri) && - !strcmp(location[0], old_location) && - !strcmp(make_model[0], old_make_model) && p->type == old_type) - { - /* - * LDAP entry for the printer exists. Printer has already been registered, - * no modifications required... - */ - - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "send_ldap_browse: No updates required for %s", p->name); - } - else - { - /* - * LDAP entry for the printer exists. Printer has already been registered, - * modify the current registration... - */ - - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "send_ldap_browse: Replace entry for %s", p->name); + free(p->ipp_txt); + p->ipp_txt = NULL; + } - for (i = 0; i < 7; i ++) - { - pmods[i] = mods + i; - pmods[i]->mod_op = LDAP_MOD_REPLACE; - } - pmods[i] = NULL; - -# if defined(HAVE_OPENLDAP) && LDAP_API_VERSION > 3000 - if ((rcmod = ldap_modify_ext_s(BrowseLDAPHandle, dn, pmods, NULL, - NULL)) != LDAP_SUCCESS) -# else - if ((rcmod = ldap_modify_s(BrowseLDAPHandle, dn, pmods)) != LDAP_SUCCESS) -# endif /* defined(HAVE_OPENLDAP) && LDAP_API_VERSION > 3000 */ - { - cupsdLogMessage(CUPSD_LOG_ERROR, - "LDAP modify for %s failed with status %d: %s", - p->name, rcmod, ldap_err2string(rcmod)); - if (rcmod == LDAP_SERVER_DOWN) - ldap_reconnect(); - } - } + if (p->printer_ref) + { + DNSServiceRefDeallocate(p->printer_ref); + p->printer_ref = NULL; } - else + + if (p->printer_txt) { /* - * No LDAP entry exists for the printer. Printer has never been registered, - * add the current registration... + * p->printer_txt is malloc'd, not _cupsStrAlloc'd... */ - send_ldap_ou(ServerName, BrowseLDAPDN, "CUPS Server"); - - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "send_ldap_browse: Add entry for %s", p->name); - - for (i = 0; i < 7; i ++) - { - pmods[i] = mods + i; - pmods[i]->mod_op = LDAP_MOD_ADD; - } - pmods[i] = NULL; - -# if defined(HAVE_OPENLDAP) && LDAP_API_VERSION > 3000 - if ((rcmod = ldap_add_ext_s(BrowseLDAPHandle, dn, pmods, NULL, - NULL)) != LDAP_SUCCESS) -# else - if ((rcmod = ldap_add_s(BrowseLDAPHandle, dn, pmods)) != LDAP_SUCCESS) -# endif /* defined(HAVE_OPENLDAP) && LDAP_API_VERSION > 3000 */ - { - cupsdLogMessage(CUPSD_LOG_ERROR, - "LDAP add for %s failed with status %d: %s", - p->name, rcmod, ldap_err2string(rcmod)); - if (rcmod == LDAP_SERVER_DOWN) - ldap_reconnect(); - } + free(p->printer_txt); + p->printer_txt = NULL; } - if (rc == LDAP_SUCCESS) - ldap_freeres(res); + /* + * Remove the printer from the array of DNS-SD printers, then clear the + * registered name... + */ + + cupsArrayRemove(DNSSDPrinters, p); + cupsdClearString(&p->reg_name); } /* - * 'ldap_dereg_printer()' - Delete printer from directory + * 'dnssdPackTxtRecord()' - Pack an array of key/value pairs into the + * TXT record format. */ -static void -ldap_dereg_printer(cupsd_printer_t *p) /* I - Printer to deregister */ +static char * /* O - TXT record */ +dnssdPackTxtRecord(int *txt_len, /* O - TXT record length */ + char *keyvalue[][2], /* I - Table of key value pairs */ + int count) /* I - Items in table */ { - char dn[1024]; /* DN of the printer */ - int rc; /* LDAP status */ - + int i; /* Looping var */ + int length; /* Length of TXT record */ + int length2; /* Length of value */ + char *txtRecord; /* TXT record buffer */ + char *cursor; /* Looping pointer */ - cupsdLogMessage(CUPSD_LOG_DEBUG2, "ldap_dereg_printer: Remove entry for %s", - p->name); /* - * Reconnect if LDAP Handle is invalid... + * Calculate the buffer size */ - if (!BrowseLDAPHandle) - { - ldap_reconnect(); - return; - } + if (count <= 0) + return (NULL); + + for (length = i = 0; i < count; i++) + length += 1 + strlen(keyvalue[i][0]) + + (keyvalue[i][1] ? 1 + strlen(keyvalue[i][1]) : 0); /* - * Get dn for printer and delete LDAP entry... + * Allocate and fill it */ - snprintf(dn, sizeof(dn), "cn=%s, ou=%s, %s", p->name, ServerName, - BrowseLDAPDN); - cupsdLogMessage(CUPSD_LOG_DEBUG2, "ldap_dereg_printer: dn=\"%s\"", dn); - -# if defined(HAVE_OPENLDAP) && LDAP_API_VERSION > 3000 - if ((rc = ldap_delete_ext_s(BrowseLDAPHandle, dn, NULL, - NULL)) != LDAP_SUCCESS) -# else - if ((rc = ldap_delete_s(BrowseLDAPHandle, dn)) != LDAP_SUCCESS) -# endif /* defined(HAVE_OPENLDAP) && LDAP_API_VERSION > 3000 */ + txtRecord = malloc(length); + if (txtRecord) { - cupsdLogMessage(CUPSD_LOG_WARN, - "LDAP delete for %s failed with status %d: %s", - p->name, rc, ldap_err2string(rc)); + *txt_len = length; - /* - * If we had a connection problem (connection timed out, etc.) - * we should reconnect and try again to delete the entry... - */ + for (cursor = txtRecord, i = 0; i < count; i++) + { + /* + * Drop in the p-string style length byte followed by the data + */ + + length = strlen(keyvalue[i][0]); + length2 = keyvalue[i][1] ? 1 + strlen(keyvalue[i][1]) : 0; + + *cursor++ = (unsigned char)(length + length2); + + memcpy(cursor, keyvalue[i][0], length); + cursor += length; - if (rc == LDAP_SERVER_DOWN || rc == LDAP_CONNECT_ERROR) - { - cupsdLogMessage(CUPSD_LOG_INFO, - "Retry deleting LDAP entry for %s after a reconnect...", p->name); - ldap_reconnect(); - -# if defined(HAVE_OPENLDAP) && LDAP_API_VERSION > 3000 - if ((rc = ldap_delete_ext_s(BrowseLDAPHandle, dn, NULL, - NULL)) != LDAP_SUCCESS) -# else - if ((rc = ldap_delete_s(BrowseLDAPHandle, dn)) != LDAP_SUCCESS) -# endif /* defined(HAVE_OPENLDAP) && LDAP_API_VERSION > 3000 */ - cupsdLogMessage(CUPSD_LOG_WARN, - "LDAP delete for %s failed with status %d: %s", - p->name, rc, ldap_err2string(rc)); + if (length2) + { + length2 --; + *cursor++ = '='; + memcpy(cursor, keyvalue[i][1], length2); + cursor += length2; + } } } + + return (txtRecord); } /* - * 'ldap_dereg_ou()' - Remove the organizational unit. + * 'dnssdRegisterCallback()' - DNSServiceRegister callback. */ static void -ldap_dereg_ou(char *ou, /* I - Organizational unit (servername) */ - char *basedn) /* I - Dase dn */ +dnssdRegisterCallback( + DNSServiceRef sdRef, /* I - DNS Service reference */ + DNSServiceFlags flags, /* I - Reserved for future use */ + DNSServiceErrorType errorCode, /* I - Error code */ + const char *name, /* I - Service name */ + const char *regtype, /* I - Service type */ + const char *domain, /* I - Domain. ".local" for now */ + void *context) /* I - User-defined context */ { - char dn[1024]; /* DN of the printer */ - int rc; /* LDAP status */ + cupsd_printer_t *p = (cupsd_printer_t *)context; + /* Current printer */ - cupsdLogMessage(CUPSD_LOG_DEBUG2, "ldap_dereg_ou: Remove entry for %s", ou); + (void)sdRef; + (void)flags; + (void)domain; - /* - * Reconnect if LDAP Handle is invalid... - */ + cupsdLogMessage(CUPSD_LOG_DEBUG2, "dnssdRegisterCallback(%s, %s) for %s (%s)", + name, regtype, p ? p->name : "Web Interface", + p ? (p->reg_name ? p->reg_name : "(null)") : "NA"); - if (!BrowseLDAPHandle) + if (errorCode) { - ldap_reconnect(); + cupsdLogMessage(CUPSD_LOG_ERROR, + "DNSServiceRegister failed with error %d", (int)errorCode); return; } - - /* - * Get dn for printer and delete LDAP entry... - */ - - snprintf(dn, sizeof(dn), "ou=%s, %s", ou, basedn); - cupsdLogMessage(CUPSD_LOG_DEBUG2, "ldap_dereg_ou: dn=\"%s\"", dn); - -# if defined(HAVE_OPENLDAP) && LDAP_API_VERSION > 3000 - if ((rc = ldap_delete_ext_s(BrowseLDAPHandle, dn, NULL, - NULL)) != LDAP_SUCCESS) -# else - if ((rc = ldap_delete_s(BrowseLDAPHandle, dn)) != LDAP_SUCCESS) -# endif /* defined(HAVE_OPENLDAP) && LDAP_API_VERSION > 3000 */ + else if (p && (!p->reg_name || _cups_strcasecmp(name, p->reg_name))) { - cupsdLogMessage(CUPSD_LOG_WARN, - "LDAP delete for %s failed with status %d: %s", - ou, rc, ldap_err2string(rc)); + cupsdLogMessage(CUPSD_LOG_INFO, "Using service name \"%s\" for \"%s\"", + name, p->name); - /* - * If we had a connection problem (connection timed out, etc.) - * we should reconnect and try again to delete the entry... - */ + cupsArrayRemove(DNSSDPrinters, p); + cupsdSetString(&p->reg_name, name); + cupsArrayAdd(DNSSDPrinters, p); - if (rc == LDAP_SERVER_DOWN || rc == LDAP_CONNECT_ERROR) - { - cupsdLogMessage(CUPSD_LOG_INFO, - "Retry deleting LDAP entry for %s after a reconnect...", ou); - ldap_reconnect(); -# if defined(HAVE_OPENLDAP) && LDAP_API_VERSION > 3000 - if ((rc = ldap_delete_ext_s(BrowseLDAPHandle, dn, NULL, - NULL)) != LDAP_SUCCESS) -# else - if ((rc = ldap_delete_s(BrowseLDAPHandle, dn)) != LDAP_SUCCESS) -# endif /* defined(HAVE_OPENLDAP) && LDAP_API_VERSION > 3000 */ - cupsdLogMessage(CUPSD_LOG_WARN, - "LDAP delete for %s failed with status %d: %s", - ou, rc, ldap_err2string(rc)); - } + LastEvent |= CUPSD_EVENT_PRINTER_MODIFIED; } } -#endif /* HAVE_LDAP */ -#ifdef HAVE_LIBSLP /* - * 'send_slp_browse()' - Register the specified printer with SLP. + * 'dnssdRegisterPrinter()' - Start sending broadcast information for a printer + * or update the broadcast contents. */ static void -send_slp_browse(cupsd_printer_t *p) /* I - Printer to register */ +dnssdRegisterPrinter(cupsd_printer_t *p)/* I - Printer */ { - char srvurl[HTTP_MAX_URI], /* Printer service URI */ - attrs[8192], /* Printer attributes */ - finishings[1024], /* Finishings to support */ - make_model[IPP_MAX_NAME * 2], - /* Make and model, quoted */ - location[IPP_MAX_NAME * 2], - /* Location, quoted */ - info[IPP_MAX_NAME * 2], /* Info, quoted */ - *src, /* Pointer to original string */ - *dst; /* Pointer to destination string */ - ipp_attribute_t *authentication; /* uri-authentication-supported value */ - SLPError error; /* SLP error, if any */ - - - cupsdLogMessage(CUPSD_LOG_DEBUG, "send_slp_browse(%p = \"%s\")", p, - p->name); - - /* - * Make the SLP service URL that conforms to the IANA - * 'printer:' template. - */ + DNSServiceErrorType se; /* dnssd errors */ + char *ipp_txt, /* IPP TXT record buffer */ + *printer_txt, /* LPD TXT record buffer */ + name[1024], /* Service name */ + *nameptr; /* Pointer into name */ + int ipp_len, /* IPP TXT record length */ + printer_len, /* LPD TXT record length */ + printer_port; /* LPD port number */ + const char *regtype; /* Registration type */ - snprintf(srvurl, sizeof(srvurl), SLP_CUPS_SRVTYPE ":%s", p->uri); - cupsdLogMessage(CUPSD_LOG_DEBUG2, "Service URL = \"%s\"", srvurl); + cupsdLogMessage(CUPSD_LOG_DEBUG2, "dnssdRegisterPrinter(%s) %s", p->name, + !p->ipp_ref ? "new" : "update"); /* - * Figure out the finishings string... + * If per-printer sharing was just disabled make sure we're not + * registered before returning. */ - if (p->type & CUPS_PRINTER_STAPLE) - strcpy(finishings, "staple"); - else - finishings[0] = '\0'; - - if (p->type & CUPS_PRINTER_BIND) - { - if (finishings[0]) - strlcat(finishings, ",bind", sizeof(finishings)); - else - strcpy(finishings, "bind"); - } - - if (p->type & CUPS_PRINTER_PUNCH) + if (!p->shared) { - if (finishings[0]) - strlcat(finishings, ",punch", sizeof(finishings)); - else - strcpy(finishings, "punch"); + dnssdDeregisterPrinter(p); + return; } - if (p->type & CUPS_PRINTER_COVER) - { - if (finishings[0]) - strlcat(finishings, ",cover", sizeof(finishings)); - else - strcpy(finishings, "cover"); - } + /* + * The registered name takes the form of " @ "... + */ - if (p->type & CUPS_PRINTER_SORT) + if (p->info && strlen(p->info) > 0) { - if (finishings[0]) - strlcat(finishings, ",sort", sizeof(finishings)); + if (DNSSDComputerName) + snprintf(name, sizeof(name), "%s @ %s", p->info, DNSSDComputerName); else - strcpy(finishings, "sort"); + strlcpy(name, p->info, sizeof(name)); } - - if (!finishings[0]) - strcpy(finishings, "none"); + else if (DNSSDComputerName) + snprintf(name, sizeof(name), "%s @ %s", p->name, DNSSDComputerName); + else + strlcpy(name, p->name, sizeof(name)); /* - * Quote any commas in the make and model, location, and info strings... + * If an existing printer was renamed, unregister it and start over... */ - for (src = p->make_model, dst = make_model; - src && *src && dst < (make_model + sizeof(make_model) - 2);) - { - if (*src == ',' || *src == '\\' || *src == ')') - *dst++ = '\\'; - - *dst++ = *src++; - } - - *dst = '\0'; - - if (!make_model[0]) - strcpy(make_model, "Unknown"); - - for (src = p->location, dst = location; - src && *src && dst < (location + sizeof(location) - 2);) - { - if (*src == ',' || *src == '\\' || *src == ')') - *dst++ = '\\'; - - *dst++ = *src++; - } - - *dst = '\0'; - - if (!location[0]) - strcpy(location, "Unknown"); + if (p->reg_name && strcmp(p->reg_name, name)) + dnssdDeregisterPrinter(p); - for (src = p->info, dst = info; - src && *src && dst < (info + sizeof(info) - 2);) + if (!p->reg_name) { - if (*src == ',' || *src == '\\' || *src == ')') - *dst++ = '\\'; - - *dst++ = *src++; + cupsdSetString(&p->reg_name, name); + cupsArrayAdd(DNSSDPrinters, p); } - *dst = '\0'; - - if (!info[0]) - strcpy(info, "Unknown"); - - /* - * Get the authentication value... - */ - - authentication = ippFindAttribute(p->attrs, "uri-authentication-supported", - IPP_TAG_KEYWORD); - - /* - * Make the SLP attribute string list that conforms to - * the IANA 'printer:' template. - */ - - snprintf(attrs, sizeof(attrs), - "(printer-uri-supported=%s)," - "(uri-authentication-supported=%s>)," -#ifdef HAVE_SSL - "(uri-security-supported=tls>)," -#else - "(uri-security-supported=none>)," -#endif /* HAVE_SSL */ - "(printer-name=%s)," - "(printer-location=%s)," - "(printer-info=%s)," - "(printer-more-info=%s)," - "(printer-make-and-model=%s)," - "(printer-type=%d)," - "(charset-supported=utf-8)," - "(natural-language-configured=%s)," - "(natural-language-supported=de,en,es,fr,it)," - "(color-supported=%s)," - "(finishings-supported=%s)," - "(sides-supported=one-sided%s)," - "(multiple-document-jobs-supported=true)" - "(ipp-versions-supported=1.0,1.1)", - p->uri, authentication->values[0].string.text, p->name, location, - info, p->uri, make_model, p->type, DefaultLanguage, - p->type & CUPS_PRINTER_COLOR ? "true" : "false", - finishings, - p->type & CUPS_PRINTER_DUPLEX ? - ",two-sided-long-edge,two-sided-short-edge" : ""); - - cupsdLogMessage(CUPSD_LOG_DEBUG2, "Attributes = \"%s\"", attrs); - /* - * Register the printer with the SLP server... + * Register IPP and (optionally) LPD... */ - error = SLPReg(BrowseSLPHandle, srvurl, BrowseTimeout, - SLP_CUPS_SRVTYPE, attrs, SLP_TRUE, slp_reg_callback, 0); - - if (error != SLP_OK) - cupsdLogMessage(CUPSD_LOG_ERROR, "SLPReg of \"%s\" failed with status %d!", p->name, - error); -} - + ipp_len = 0; /* anti-compiler-warning-code */ + ipp_txt = dnssdBuildTxtRecord(&ipp_len, p, 0); -/* - * 'slp_attr_callback()' - SLP attribute callback - */ + if (p->ipp_ref && + (ipp_len != p->ipp_len || memcmp(ipp_txt, p->ipp_txt, ipp_len))) + { + /* + * Update the existing registration... + */ -static SLPBoolean /* O - SLP_TRUE for success */ -slp_attr_callback( - SLPHandle hslp, /* I - SLP handle */ - const char *attrlist, /* I - Attribute list */ - SLPError errcode, /* I - Parsing status for this attr */ - void *cookie) /* I - Current printer */ -{ - char *tmp = 0; /* Temporary string */ - cupsd_printer_t *p = (cupsd_printer_t*)cookie; - /* Current printer */ + /* A TTL of 0 means use record's original value (Radar 3176248) */ + if ((se = DNSServiceUpdateRecord(p->ipp_ref, NULL, 0, ipp_len, ipp_txt, + 0)) == kDNSServiceErr_NoError) + { + if (p->ipp_txt) + free(p->ipp_txt); + p->ipp_txt = ipp_txt; + p->ipp_len = ipp_len; + ipp_txt = NULL; + } + else + { + /* + * Failed to update record, lets close this reference and move on... + */ - (void)hslp; /* anti-compiler-warning-code */ + cupsdLogMessage(CUPSD_LOG_ERROR, + "Unable to update IPP DNS-SD record for %s - %d", p->name, + se); - /* - * Bail if there was an error - */ + DNSServiceRefDeallocate(p->ipp_ref); + p->ipp_ref = NULL; + } + } - if (errcode != SLP_OK) - return (SLP_TRUE); + if (!p->ipp_ref) + { + /* + * Initial registration. Use the _fax-ipp regtype for fax queues... + */ - /* - * Parse the attrlist to obtain things needed to build CUPS browse packet - */ + regtype = (p->type & CUPS_PRINTER_FAX) ? "_fax-ipp._tcp" : DNSSDRegType; - memset(p, 0, sizeof(cupsd_printer_t)); + cupsdLogMessage(CUPSD_LOG_DEBUG, + "Registering DNS-SD printer %s with name \"%s\" and " + "type \"%s\"", p->name, name, regtype); - if (slp_get_attr(attrlist, "(printer-location=", &(p->location))) - return (SLP_FALSE); - if (slp_get_attr(attrlist, "(printer-info=", &(p->info))) - return (SLP_FALSE); - if (slp_get_attr(attrlist, "(printer-make-and-model=", &(p->make_model))) - return (SLP_FALSE); - if (!slp_get_attr(attrlist, "(printer-type=", &tmp)) - p->type = atoi(tmp); - else - p->type = CUPS_PRINTER_REMOTE; + /* + * Register the queue, dropping characters as needed until we succeed... + */ - cupsdClearString(&tmp); + nameptr = name + strlen(name); - return (SLP_TRUE); -} + do + { + p->ipp_ref = DNSSDRef; + if ((se = DNSServiceRegister(&p->ipp_ref, kDNSServiceFlagsShareConnection, + 0, name, regtype, NULL, NULL, + htons(DNSSDPort), ipp_len, ipp_txt, + dnssdRegisterCallback, + p)) == kDNSServiceErr_BadParam) + { + /* + * Name is too long, drop trailing characters, taking into account + * UTF-8 encoding... + */ + nameptr --; -/* - * 'slp_dereg_printer()' - SLPDereg() the specified printer - */ + while (nameptr > name && (*nameptr & 0xc0) == 0x80) + nameptr --; -static void -slp_dereg_printer(cupsd_printer_t *p) /* I - Printer */ -{ - char srvurl[HTTP_MAX_URI]; /* Printer service URI */ + if (nameptr > name) + *nameptr = '\0'; + } + } + while (se == kDNSServiceErr_BadParam && nameptr > name); + if (se == kDNSServiceErr_NoError) + { + p->ipp_txt = ipp_txt; + p->ipp_len = ipp_len; + ipp_txt = NULL; + } + else + cupsdLogMessage(CUPSD_LOG_WARN, + "DNS-SD IPP registration of \"%s\" failed: %d", + p->name, se); + } - cupsdLogMessage(CUPSD_LOG_DEBUG, "slp_dereg_printer: printer=\"%s\"", p->name); + if (ipp_txt) + free(ipp_txt); - if (!(p->type & CUPS_PRINTER_REMOTE)) + if (BrowseLocalProtocols & BROWSE_LPD) { - /* - * Make the SLP service URL that conforms to the IANA - * 'printer:' template. - */ - - snprintf(srvurl, sizeof(srvurl), SLP_CUPS_SRVTYPE ":%s", p->uri); + printer_len = 0; /* anti-compiler-warning-code */ + printer_port = 515; + printer_txt = dnssdBuildTxtRecord(&printer_len, p, 1); + } + else + { + printer_len = 0; + printer_port = 0; + printer_txt = NULL; + } + if (p->printer_ref && + (printer_len != p->printer_len || + memcmp(printer_txt, p->printer_txt, printer_len))) + { /* - * Deregister the printer... + * Update the existing registration... */ - SLPDereg(BrowseSLPHandle, srvurl, slp_reg_callback, 0); - } -} - - -/* - * 'slp_get_attr()' - Get an attribute from an SLP registration. - */ - -static int /* O - 0 on success */ -slp_get_attr(const char *attrlist, /* I - Attribute list string */ - const char *tag, /* I - Name of attribute */ - char **valbuf) /* O - Value */ -{ - char *ptr1, /* Pointer into string */ - *ptr2; /* ... */ - - - cupsdClearString(valbuf); - - if ((ptr1 = strstr(attrlist, tag)) != NULL) - { - ptr1 += strlen(tag); + /* A TTL of 0 means use record's original value (Radar 3176248) */ + if ((se = DNSServiceUpdateRecord(p->printer_ref, NULL, 0, printer_len, + printer_txt, + 0)) == kDNSServiceErr_NoError) + { + if (p->printer_txt) + free(p->printer_txt); - if ((ptr2 = strchr(ptr1,')')) != NULL) + p->printer_txt = printer_txt; + p->printer_len = printer_len; + printer_txt = NULL; + } + else { /* - * Copy the value... - */ - - *valbuf = calloc(ptr2 - ptr1 + 1, 1); - strncpy(*valbuf, ptr1, ptr2 - ptr1); - - /* - * Dequote the value... + * Failed to update record, lets close this reference and move on... */ - for (ptr1 = *valbuf; *ptr1; ptr1 ++) - if (*ptr1 == '\\' && ptr1[1]) - _cups_strcpy(ptr1, ptr1 + 1); + cupsdLogMessage(CUPSD_LOG_ERROR, + "Unable to update LPD DNS-SD record for %s - %d", + p->name, se); - return (0); + DNSServiceRefDeallocate(p->printer_ref); + p->printer_ref = NULL; } } - return (-1); -} - + if (!p->printer_ref) + { + /* + * Initial registration... + */ -/* - * 'slp_reg_callback()' - Empty SLPRegReport. - */ + cupsdLogMessage(CUPSD_LOG_DEBUG, + "Registering DNS-SD printer %s with name \"%s\" and " + "type \"_printer._tcp\"", p->name, name); -static void -slp_reg_callback(SLPHandle hslp, /* I - SLP handle */ - SLPError errcode, /* I - Error code, if any */ - void *cookie) /* I - App data */ -{ - (void)hslp; - (void)errcode; - (void)cookie; + p->printer_ref = DNSSDRef; + if ((se = DNSServiceRegister(&p->printer_ref, + kDNSServiceFlagsShareConnection, + 0, name, "_printer._tcp", NULL, NULL, + htons(printer_port), printer_len, printer_txt, + dnssdRegisterCallback, + p)) == kDNSServiceErr_NoError) + { + p->printer_txt = printer_txt; + p->printer_len = printer_len; + printer_txt = NULL; + } + else + cupsdLogMessage(CUPSD_LOG_WARN, + "DNS-SD LPD registration of \"%s\" failed: %d", + p->name, se); + } - return; + if (printer_txt) + free(printer_txt); } /* - * 'slp_url_callback()' - SLP service url callback + * 'dnssdStop()' - Stop all DNS-SD registrations. */ -static SLPBoolean /* O - TRUE = OK, FALSE = error */ -slp_url_callback( - SLPHandle hslp, /* I - SLP handle */ - const char *srvurl, /* I - URL of service */ - unsigned short lifetime, /* I - Life of service */ - SLPError errcode, /* I - Existing error code */ - void *cookie) /* I - Pointer to service list */ +static void +dnssdStop(void) { - slpsrvurl_t *s, /* New service entry */ - **head; /* Pointer to head of entry */ + cupsd_printer_t *p; /* Current printer */ /* - * Let the compiler know we won't be using these vars... + * De-register the individual printers */ - (void)hslp; - (void)lifetime; + for (p = (cupsd_printer_t *)cupsArrayFirst(Printers); + p; + p = (cupsd_printer_t *)cupsArrayNext(Printers)) + dnssdDeregisterPrinter(p); /* - * Bail if there was an error + * Shutdown the rest of the service refs... */ - if (errcode != SLP_OK) - return (SLP_TRUE); - - /* - * Grab the head of the list... - */ + if (WebIFRef) + { + DNSServiceRefDeallocate(WebIFRef); + WebIFRef = NULL; + } - head = (slpsrvurl_t**)cookie; + cupsdRemoveSelect(DNSServiceRefSockFD(DNSSDRef)); - /* - * Allocate a *temporary* slpsrvurl_t to hold this entry. - */ + DNSServiceRefDeallocate(DNSSDRef); + DNSSDRef = NULL; - if ((s = (slpsrvurl_t *)calloc(1, sizeof(slpsrvurl_t))) == NULL) - return (SLP_FALSE); + cupsArrayDelete(DNSSDPrinters); + DNSSDPrinters = NULL; - /* - * Copy the SLP service URL... - */ + DNSSDPort = 0; +} - strlcpy(s->url, srvurl, sizeof(s->url)); - /* - * Link the SLP service URL into the head of the list - */ +/* + * 'dnssdUpdate()' - Handle DNS-SD queries. + */ - if (*head) - s->next = *head; +static void +dnssdUpdate(void) +{ + DNSServiceErrorType sdErr; /* Service discovery error */ - *head = s; - return (SLP_TRUE); + if ((sdErr = DNSServiceProcessResult(DNSSDRef)) != kDNSServiceErr_NoError) + { + cupsdLogMessage(CUPSD_LOG_ERROR, + "DNS Service Discovery registration error %d!", + sdErr); + dnssdStop(); + } } -#endif /* HAVE_LIBSLP */ +#endif /* HAVE_DNSSD */ /* - * 'update_cups_browse()' - Update the browse lists using the CUPS protocol. + * 'get_auth_info_required()' - Get the auth-info-required value to advertise. */ -static void -update_cups_browse(void) +static char * /* O - String or NULL if none */ +get_auth_info_required( + cupsd_printer_t *p, /* I - Printer */ + char *buffer, /* I - Value buffer */ + size_t bufsize) /* I - Size of value buffer */ { - int i; /* Looping var */ - int auth; /* Authorization status */ - int len; /* Length of name string */ - int bytes; /* Number of bytes left */ - char packet[1541], /* Broadcast packet */ - *pptr; /* Pointer into packet */ - socklen_t srclen; /* Length of source address */ - http_addr_t srcaddr; /* Source address */ - char srcname[1024]; /* Source hostname */ - unsigned address[4]; /* Source address */ - unsigned type; /* Printer type */ - unsigned state; /* Printer state */ - char uri[HTTP_MAX_URI], /* Printer URI */ - host[HTTP_MAX_URI], /* Host portion of URI */ - resource[HTTP_MAX_URI], /* Resource portion of URI */ - info[IPP_MAX_NAME], /* Information string */ - location[IPP_MAX_NAME], /* Location string */ - make_model[IPP_MAX_NAME];/* Make and model string */ - int num_attrs; /* Number of attributes */ - cups_option_t *attrs; /* Attributes */ + cupsd_location_t *auth; /* Pointer to authentication element */ + char resource[1024]; /* Printer/class resource path */ /* - * Read a packet from the browse socket... + * If auth-info-required is set for this printer, return that... */ - srclen = sizeof(srcaddr); - if ((bytes = recvfrom(BrowseSocket, packet, sizeof(packet) - 1, 0, - (struct sockaddr *)&srcaddr, &srclen)) < 0) + if (p->num_auth_info_required > 0 && strcmp(p->auth_info_required[0], "none")) { - /* - * "Connection refused" is returned under Linux if the destination port - * or address is unreachable from a previous sendto(); check for the - * error here and ignore it for now... - */ + int i; /* Looping var */ + char *bufptr; /* Pointer into buffer */ - if (errno != ECONNREFUSED && errno != EAGAIN) + for (i = 0, bufptr = buffer; i < p->num_auth_info_required; i ++) { - cupsdLogMessage(CUPSD_LOG_ERROR, "Browse recv failed - %s.", - strerror(errno)); - cupsdLogMessage(CUPSD_LOG_ERROR, "CUPS browsing turned off."); - -#ifdef WIN32 - closesocket(BrowseSocket); -#else - close(BrowseSocket); -#endif /* WIN32 */ + if (bufptr >= (buffer + bufsize - 2)) + break; - cupsdRemoveSelect(BrowseSocket); - BrowseSocket = -1; + if (i) + *bufptr++ = ','; - BrowseLocalProtocols &= ~BROWSE_CUPS; - BrowseRemoteProtocols &= ~BROWSE_CUPS; + strlcpy(bufptr, p->auth_info_required[i], bufsize - (bufptr - buffer)); + bufptr += strlen(bufptr); } - return; + return (buffer); } - packet[bytes] = '\0'; - - /* - * If we're about to sleep, ignore incoming browse packets. - */ - - if (Sleeping) - return; - /* - * Figure out where it came from... + * Figure out the authentication data requirements to advertise... */ -#ifdef AF_INET6 - if (srcaddr.addr.sa_family == AF_INET6) - { - address[0] = ntohl(srcaddr.ipv6.sin6_addr.s6_addr32[0]); - address[1] = ntohl(srcaddr.ipv6.sin6_addr.s6_addr32[1]); - address[2] = ntohl(srcaddr.ipv6.sin6_addr.s6_addr32[2]); - address[3] = ntohl(srcaddr.ipv6.sin6_addr.s6_addr32[3]); - } - else -#endif /* AF_INET6 */ - { - address[0] = 0; - address[1] = 0; - address[2] = 0; - address[3] = ntohl(srcaddr.ipv4.sin_addr.s_addr); - } - - if (HostNameLookups) - httpAddrLookup(&srcaddr, srcname, sizeof(srcname)); + if (p->type & CUPS_PRINTER_CLASS) + snprintf(resource, sizeof(resource), "/classes/%s", p->name); else - httpAddrString(&srcaddr, srcname, sizeof(srcname)); - - len = strlen(srcname); + snprintf(resource, sizeof(resource), "/printers/%s", p->name); - /* - * Do ACL stuff... - */ + if ((auth = cupsdFindBest(resource, HTTP_POST)) == NULL || + auth->type == CUPSD_AUTH_NONE) + auth = cupsdFindPolicyOp(p->op_policy_ptr, IPP_PRINT_JOB); - if (BrowseACL) + if (auth) { - if (httpAddrLocalhost(&srcaddr) || !_cups_strcasecmp(srcname, "localhost")) - { - /* - * Access from localhost (127.0.0.1) is always allowed... - */ + int auth_type; /* Authentication type */ - auth = CUPSD_AUTH_ALLOW; - } - else - { - /* - * Do authorization checks on the domain/address... - */ + if ((auth_type = auth->type) == CUPSD_AUTH_DEFAULT) + auth_type = DefaultAuthType; - switch (BrowseACL->order_type) - { - default : - auth = CUPSD_AUTH_DENY; /* anti-compiler-warning-code */ - break; + switch (auth_type) + { + case CUPSD_AUTH_NONE : + return (NULL); - case CUPSD_AUTH_ALLOW : /* Order Deny,Allow */ - auth = CUPSD_AUTH_ALLOW; + case CUPSD_AUTH_NEGOTIATE : + strlcpy(buffer, "negotiate", bufsize); + break; - if (cupsdCheckAuth(address, srcname, len, BrowseACL->deny)) - auth = CUPSD_AUTH_DENY; + default : + strlcpy(buffer, "username,password", bufsize); + break; + } - if (cupsdCheckAuth(address, srcname, len, BrowseACL->allow)) - auth = CUPSD_AUTH_ALLOW; - break; + return (buffer); + } - case CUPSD_AUTH_DENY : /* Order Allow,Deny */ - auth = CUPSD_AUTH_DENY; + return ("none"); +} - if (cupsdCheckAuth(address, srcname, len, BrowseACL->allow)) - auth = CUPSD_AUTH_ALLOW; - if (cupsdCheckAuth(address, srcname, len, BrowseACL->deny)) - auth = CUPSD_AUTH_DENY; - break; - } - } - } - else - auth = CUPSD_AUTH_ALLOW; +#ifdef __APPLE__ +/* + * 'get_hostconfig()' - Get an /etc/hostconfig service setting. + */ - if (auth == CUPSD_AUTH_DENY) - { - cupsdLogMessage(CUPSD_LOG_DEBUG, - "update_cups_browse: Refused %d bytes from %s", bytes, - srcname); - return; - } +static int /* O - 1 for YES or AUTOMATIC, 0 for NO */ +get_hostconfig(const char *name) /* I - Name of service */ +{ + cups_file_t *fp; /* Hostconfig file */ + char line[1024], /* Line from file */ + *ptr; /* Pointer to value */ + int state = 1; /* State of service */ - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "update_cups_browse: (%d bytes from %s) %s", bytes, - srcname, packet); /* - * Parse packet... + * Try opening the /etc/hostconfig file; if we can't open it, assume that + * the service is enabled/auto. */ - if (sscanf(packet, "%x%x%1023s", &type, &state, uri) < 3) - { - cupsdLogMessage(CUPSD_LOG_WARN, - "update_cups_browse: Garbled browse packet - %s", packet); - return; - } - - strcpy(location, "Location Unknown"); - strcpy(info, "No Information Available"); - make_model[0] = '\0'; - num_attrs = 0; - attrs = NULL; - - if ((pptr = strchr(packet, '\"')) != NULL) + if ((fp = cupsFileOpen("/etc/hostconfig", "r")) != NULL) { /* - * Have extended information; can't use sscanf for it because not all - * sscanf's allow empty strings with %[^\"]... + * Read lines from the file until we find the service... */ - for (i = 0, pptr ++; - i < (sizeof(location) - 1) && *pptr && *pptr != '\"'; - i ++, pptr ++) - location[i] = *pptr; - - if (i) - location[i] = '\0'; - - if (*pptr == '\"') - pptr ++; - - while (*pptr && isspace(*pptr & 255)) - pptr ++; - - if (*pptr == '\"') + while (cupsFileGets(fp, line, sizeof(line))) { - for (i = 0, pptr ++; - i < (sizeof(info) - 1) && *pptr && *pptr != '\"'; - i ++, pptr ++) - info[i] = *pptr; - - info[i] = '\0'; - - if (*pptr == '\"') - pptr ++; + if (line[0] == '#' || (ptr = strchr(line, '=')) == NULL) + continue; - while (*pptr && isspace(*pptr & 255)) - pptr ++; + *ptr++ = '\0'; - if (*pptr == '\"') + if (!_cups_strcasecmp(line, name)) { - for (i = 0, pptr ++; - i < (sizeof(make_model) - 1) && *pptr && *pptr != '\"'; - i ++, pptr ++) - make_model[i] = *pptr; - - if (*pptr == '\"') - pptr ++; - - make_model[i] = '\0'; + /* + * Found the service, see if it is set to "-NO-"... + */ - if (*pptr) - num_attrs = cupsParseOptions(pptr, num_attrs, &attrs); + if (!_cups_strncasecmp(ptr, "-NO-", 4)) + state = 0; + break; } } - } - - DEBUG_puts(packet); - DEBUG_printf(("type=%x, state=%x, uri=\"%s\"\n" - "location=\"%s\", info=\"%s\", make_model=\"%s\"\n", - type, state, uri, location, info, make_model)); - - /* - * Pull the URI apart to see if this is a local or remote printer... - */ - if (is_local_queue(uri, host, sizeof(host), resource, sizeof(resource))) - { - cupsFreeOptions(num_attrs, attrs); - return; + cupsFileClose(fp); } - /* - * Do relaying... - */ - - for (i = 0; i < NumRelays; i ++) - if (cupsdCheckAuth(address, srcname, len, Relays[i].from)) - if (sendto(BrowseSocket, packet, bytes, 0, - (struct sockaddr *)&(Relays[i].to), - httpAddrLength(&(Relays[i].to))) <= 0) - { - cupsdLogMessage(CUPSD_LOG_ERROR, - "update_cups_browse: sendto failed for relay %d - %s.", - i + 1, strerror(errno)); - cupsFreeOptions(num_attrs, attrs); - return; - } - - /* - * Process the browse data... - */ - - process_browse_data(uri, host, resource, (cups_ptype_t)type, - (ipp_pstate_t)state, location, info, make_model, - num_attrs, attrs); + return (state); } +#endif /* __APPLE__ */ /* @@ -5472,41 +1313,6 @@ update_lpd(int onoff) /* - 1 = turn on, 0 = turn off */ } -/* - * 'update_polling()' - Read status messages from the poll daemons. - */ - -static void -update_polling(void) -{ - char *ptr, /* Pointer to end of line in buffer */ - message[1024]; /* Pointer to message text */ - int loglevel; /* Log level for message */ - - - while ((ptr = cupsdStatBufUpdate(PollStatusBuffer, &loglevel, - message, sizeof(message))) != NULL) - { - if (loglevel == CUPSD_LOG_INFO) - cupsdLogMessage(CUPSD_LOG_INFO, "%s", message); - - if (!strchr(PollStatusBuffer->buffer, '\n')) - break; - } - - if (ptr == NULL && !PollStatusBuffer->bufused) - { - /* - * All polling processes have died; stop polling... - */ - - cupsdLogMessage(CUPSD_LOG_ERROR, - "update_polling: all polling processes have exited!"); - cupsdStopPolling(); - } -} - - /* * 'update_smb()' - Update the SMB configuration as needed. */ diff --git a/scheduler/dirsvc.h b/scheduler/dirsvc.h index 933a057ba..0625fd1ca 100644 --- a/scheduler/dirsvc.h +++ b/scheduler/dirsvc.h @@ -13,69 +13,14 @@ * file is missing or damaged, see the license at "http://www.cups.org/". */ -/* - * Include necessary headers... - */ - -#ifdef HAVE_LIBSLP -# include -#endif /* HAVE_LIBSLP */ - -#ifdef HAVE_LDAP -# ifdef __sun -# include -# endif /* __sun */ -# include -# ifdef HAVE_LDAP_SSL_H -# include -# endif /* HAVE_LDAP_SSL_H */ -#endif /* HAVE_LDAP */ - /* * Browse protocols... */ -#define BROWSE_CUPS 1 /* CUPS */ -#define BROWSE_SLP 2 /* SLPv2 */ -#define BROWSE_LDAP 4 /* LDAP */ -#define BROWSE_DNSSD 8 /* DNS Service Discovery (aka Bonjour) */ -#define BROWSE_SMB 16 /* SMB/Samba */ -#define BROWSE_LPD 32 /* LPD via xinetd or launchd */ -#define BROWSE_ALL 63 /* All protocols */ - - -/* - * Browse address... - */ - -typedef struct -{ - char iface[32]; /* Destination interface */ - http_addr_t to; /* Destination address */ -} cupsd_dirsvc_addr_t; - - -/* - * Relay structure... - */ - -typedef struct -{ - cups_array_t *from; /* Source address/name mask(s) */ - http_addr_t to; /* Destination address */ -} cupsd_dirsvc_relay_t; - - -/* - * Polling structure... - */ - -typedef struct -{ - char hostname[64]; /* Hostname (actually, IP address) */ - int port; /* Port number */ - int pid; /* Current poll server PID */ -} cupsd_dirsvc_poll_t; +#define BROWSE_DNSSD 1 /* DNS Service Discovery (aka Bonjour) */ +#define BROWSE_SMB 2 /* SMB/Samba */ +#define BROWSE_LPD 4 /* LPD via xinetd or launchd */ +#define BROWSE_ALL 7 /* All protocols */ /* @@ -87,50 +32,8 @@ VAR int Browsing VALUE(TRUE), BrowseWebIF VALUE(FALSE), /* Whether the web interface is advertised */ BrowseLocalProtocols - VALUE(BROWSE_ALL), + VALUE(BROWSE_ALL); /* Protocols to support for local printers */ - BrowseRemoteProtocols - VALUE(BROWSE_ALL), - /* Protocols to support for remote printers */ - BrowseShortNames VALUE(TRUE), - /* Short names for remote printers? */ - BrowseSocket VALUE(-1), - /* Socket for browsing */ - BrowsePort VALUE(IPP_PORT), - /* Port number for broadcasts */ - BrowseInterval VALUE(DEFAULT_INTERVAL), - /* Broadcast interval in seconds */ - BrowseTimeout VALUE(DEFAULT_TIMEOUT), - /* Time out for printers in seconds */ - UseNetworkDefault VALUE(CUPS_DEFAULT_USE_NETWORK_DEFAULT), - /* Use the network default printer? */ - NumBrowsers VALUE(0); - /* Number of broadcast addresses */ -VAR char *BrowseLocalOptions - VALUE(NULL), - /* Options to add to local printer URIs */ - *BrowseRemoteOptions - VALUE(NULL); - /* Options to add to remote printer URIs */ -VAR cupsd_dirsvc_addr_t *Browsers VALUE(NULL); - /* Broadcast addresses */ -VAR cupsd_location_t *BrowseACL VALUE(NULL); - /* Browser access control list */ -VAR cupsd_printer_t *BrowseNext VALUE(NULL); - /* Next class/printer to broadcast */ -VAR int NumRelays VALUE(0); - /* Number of broadcast relays */ -VAR cupsd_dirsvc_relay_t *Relays VALUE(NULL); - /* Broadcast relays */ -VAR int NumPolled VALUE(0); - /* Number of polled servers */ -VAR cupsd_dirsvc_poll_t *Polled VALUE(NULL); - /* Polled servers */ -VAR int PollPipe VALUE(0); - /* Status pipe for pollers */ -VAR cupsd_statbuf_t *PollStatusBuffer VALUE(NULL); - /* Status buffer for pollers */ - #ifdef HAVE_DNSSD VAR char *DNSSDComputerName VALUE(NULL), /* Computer/server name */ @@ -146,39 +49,10 @@ VAR cups_array_t *DNSSDPrinters VALUE(NULL); /* Printers we have registered */ VAR DNSServiceRef DNSSDRef VALUE(NULL), /* Master DNS-SD service reference */ - WebIFRef VALUE(NULL), + WebIFRef VALUE(NULL); /* Service reference for the web interface */ - RemoteRef VALUE(NULL); - /* Remote printer browse reference */ #endif /* HAVE_DNSSD */ -#ifdef HAVE_LIBSLP -VAR SLPHandle BrowseSLPHandle VALUE(NULL); - /* SLP API handle */ -VAR time_t BrowseSLPRefresh VALUE(0); - /* Next SLP refresh time */ -#endif /* HAVE_LIBSLP */ - -#ifdef HAVE_LDAP -VAR LDAP *BrowseLDAPHandle VALUE(NULL); - /* Handle to LDAP server */ -VAR time_t BrowseLDAPRefresh VALUE(0); - /* Next LDAP refresh time */ -VAR char *BrowseLDAPBindDN VALUE(NULL), - /* LDAP login DN */ - *BrowseLDAPDN VALUE(NULL), - /* LDAP search DN */ - *BrowseLDAPPassword VALUE(NULL), - /* LDAP login password */ - *BrowseLDAPServer VALUE(NULL); - /* LDAP server to use */ -VAR int BrowseLDAPUpdate VALUE(TRUE); - /* enables LDAP updates */ -# ifdef HAVE_LDAP_SSL -VAR char *BrowseLDAPCACertFile VALUE(NULL); - /* LDAP CA CERT file to use */ -# endif /* HAVE_LDAP_SSL */ -#endif /* HAVE_LDAP */ VAR char *LPDConfigFile VALUE(NULL), /* LPD configuration file */ *SMBConfigFile VALUE(NULL); @@ -190,22 +64,12 @@ VAR char *LPDConfigFile VALUE(NULL), */ extern void cupsdDeregisterPrinter(cupsd_printer_t *p, int removeit); -extern void cupsdLoadRemoteCache(void); extern void cupsdRegisterPrinter(cupsd_printer_t *p); -extern void cupsdRestartPolling(void); -extern void cupsdSaveRemoteCache(void); -extern void cupsdSendBrowseList(void); extern void cupsdStartBrowsing(void); -extern void cupsdStartPolling(void); extern void cupsdStopBrowsing(void); -extern void cupsdStopPolling(void); #ifdef HAVE_DNSSD extern void cupsdUpdateDNSSDName(void); #endif /* HAVE_DNSSD */ -#ifdef HAVE_LDAP -extern void cupsdUpdateLDAPBrowse(void); -#endif /* HAVE_LDAP */ -extern void cupsdUpdateSLPBrowse(void); /* diff --git a/scheduler/ipp.c b/scheduler/ipp.c index 67ece2b5a..63e7e7062 100644 --- a/scheduler/ipp.c +++ b/scheduler/ipp.c @@ -45,7 +45,6 @@ * feed URI. * check_quotas() - Check quotas for a printer and user. * close_job() - Close a multi-file job. - * copy_attribute() - Copy a single attribute. * copy_attrs() - Copy attributes from one request to another. * copy_banner() - Copy a banner file to the requests directory * for the specified job. @@ -169,8 +168,6 @@ static void cancel_job(cupsd_client_t *con, ipp_attribute_t *uri); static void cancel_subscription(cupsd_client_t *con, int id); static int check_rss_recipient(const char *recipient); static int check_quotas(cupsd_client_t *con, cupsd_printer_t *p); -static ipp_attribute_t *copy_attribute(ipp_t *to, ipp_attribute_t *attr, - int quickcopy); static void close_job(cupsd_client_t *con, ipp_attribute_t *uri); static void copy_attrs(ipp_t *to, ipp_t *from, cups_array_t *ra, ipp_tag_t group, int quickcopy, @@ -850,8 +847,7 @@ cupsdTimeoutJob(cupsd_job_t *job) /* I - Job to timeout */ printer = cupsdFindDest(job->dest); attr = ippFindAttribute(job->attrs, "job-sheets", IPP_TAG_NAME); - if (printer && - !(printer->type & (CUPS_PRINTER_REMOTE | CUPS_PRINTER_IMPLICIT)) && + if (printer && !(printer->type & CUPS_PRINTER_REMOTE) && attr && attr->num_values > 1) { /* @@ -966,7 +962,6 @@ add_class(cupsd_client_t *con, /* I - Client connection */ cups_ptype_t dtype; /* Destination type */ ipp_attribute_t *attr; /* Printer attribute */ int modify; /* Non-zero if we just modified */ - char newname[IPP_MAX_NAME]; /* New class name */ int need_restart_job; /* Need to restart job? */ @@ -1020,8 +1015,7 @@ add_class(cupsd_client_t *con, /* I - Client connection */ * Class doesn't exist; see if we have a printer of the same name... */ - if ((pclass = cupsdFindPrinter(resource + 9)) != NULL && - !(pclass->type & CUPS_PRINTER_DISCOVERED)) + if ((pclass = cupsdFindPrinter(resource + 9)) != NULL) { /* * Yes, return an error... @@ -1046,56 +1040,6 @@ add_class(cupsd_client_t *con, /* I - Client connection */ pclass = cupsdAddClass(resource + 9); modify = 0; } - else if (pclass->type & CUPS_PRINTER_IMPLICIT) - { - /* - * Check the default policy, then rename the implicit class to "AnyClass" - * or remove it... - */ - - if ((status = cupsdCheckPolicy(DefaultPolicyPtr, con, NULL)) != HTTP_OK) - { - send_http_error(con, status, NULL); - return; - } - - if (ImplicitAnyClasses) - { - snprintf(newname, sizeof(newname), "Any%s", resource + 9); - cupsdRenamePrinter(pclass, newname); - } - else - cupsdDeletePrinter(pclass, 1); - - /* - * Add the class as a new local class... - */ - - pclass = cupsdAddClass(resource + 9); - modify = 0; - } - else if (pclass->type & CUPS_PRINTER_DISCOVERED) - { - /* - * Check the default policy, then rename the remote class to "Class"... - */ - - if ((status = cupsdCheckPolicy(DefaultPolicyPtr, con, NULL)) != HTTP_OK) - { - send_http_error(con, status, NULL); - return; - } - - snprintf(newname, sizeof(newname), "%s@%s", resource + 9, pclass->hostname); - cupsdRenamePrinter(pclass, newname); - - /* - * Add the class as a new local class... - */ - - pclass = cupsdAddClass(resource + 9); - modify = 0; - } else if ((status = cupsdCheckPolicy(pclass->op_policy_ptr, con, NULL)) != HTTP_OK) { @@ -1627,8 +1571,7 @@ add_job(cupsd_client_t *con, /* I - Client connection */ return (NULL); } - job->dtype = printer->type & (CUPS_PRINTER_CLASS | CUPS_PRINTER_IMPLICIT | - CUPS_PRINTER_REMOTE); + job->dtype = printer->type & (CUPS_PRINTER_CLASS | CUPS_PRINTER_REMOTE); job->attrs = con->request; job->dirty = 1; con->request = ippNewRequest(job->attrs->request.op.operation_id); @@ -1717,10 +1660,10 @@ add_job(cupsd_client_t *con, /* I - Client connection */ { _cupsStrFree(attr->values[i].string.text); attr->values[i].string.text = NULL; - if (attr->values[i].string.charset) + if (attr->values[i].string.language) { - _cupsStrFree(attr->values[i].string.charset); - attr->values[i].string.charset = NULL; + _cupsStrFree(attr->values[i].string.language); + attr->values[i].string.language = NULL; } } @@ -1813,8 +1756,7 @@ add_job(cupsd_client_t *con, /* I - Client connection */ job->state_value = IPP_JOB_PENDING; } - if (!(printer->type & (CUPS_PRINTER_REMOTE | CUPS_PRINTER_IMPLICIT)) || - Classification) + if (!(printer->type & CUPS_PRINTER_REMOTE) || Classification) { /* * Add job sheets options... @@ -1947,7 +1889,7 @@ add_job(cupsd_client_t *con, /* I - Client connection */ * See if we need to add the starting sheet... */ - if (!(printer->type & (CUPS_PRINTER_REMOTE | CUPS_PRINTER_IMPLICIT))) + if (!(printer->type & CUPS_PRINTER_REMOTE)) { cupsdLogJob(job, CUPSD_LOG_INFO, "Adding start banner page \"%s\".", attr->values[0].string.text); @@ -2022,7 +1964,7 @@ add_job_state_reasons( cupsd_job_t *job) /* I - Job info */ { cupsd_printer_t *dest; /* Destination printer */ - + ipp_attribute_t *attr; /* job-hold attribute */ cupsdLogMessage(CUPSD_LOG_DEBUG2, "add_job_state_reasons(%p[%d], %d)", con, con->http.fd, job ? job->id : 0); @@ -2041,10 +1983,11 @@ add_job_state_reasons( break; case IPP_JOB_HELD : - if (ippFindAttribute(job->attrs, "job-hold-until", - IPP_TAG_KEYWORD) != NULL || - ippFindAttribute(job->attrs, "job-hold-until", - IPP_TAG_NAME) != NULL) + if ((attr = ippFindAttribute(job->attrs, "job-hold-until", + IPP_TAG_KEYWORD)) == NULL) + attr = ippFindAttribute(job->attrs, "job-hold-until", IPP_TAG_NAME); + + if (!attr || strcmp(attr->values[0].string.text, "no-hold")) ippAddString(con->response, IPP_TAG_JOB, IPP_TAG_KEYWORD, "job-state-reasons", NULL, "job-hold-until-specified"); else @@ -2298,7 +2241,7 @@ add_job_subscriptions( * Free and remove this attribute... */ - _ippFreeAttr(attr); + ippDeleteAttribute(NULL, attr); if (prev) prev->next = next; @@ -2359,7 +2302,6 @@ add_printer(cupsd_client_t *con, /* I - Client connection */ char srcfile[1024], /* Source Script/PPD file */ dstfile[1024]; /* Destination Script/PPD file */ int modify; /* Non-zero if we are modifying */ - char newname[IPP_MAX_NAME]; /* New printer name */ int changed_driver, /* Changed the PPD/interface script? */ need_restart_job, /* Need to restart job? */ set_device_uri, /* Did we set the device URI? */ @@ -2415,8 +2357,7 @@ add_printer(cupsd_client_t *con, /* I - Client connection */ * Printer doesn't exist; see if we have a class of the same name... */ - if ((printer = cupsdFindClass(resource + 10)) != NULL && - !(printer->type & CUPS_PRINTER_DISCOVERED)) + if ((printer = cupsdFindClass(resource + 10)) != NULL) { /* * Yes, return an error... @@ -2441,58 +2382,6 @@ add_printer(cupsd_client_t *con, /* I - Client connection */ printer = cupsdAddPrinter(resource + 10); modify = 0; } - else if (printer->type & CUPS_PRINTER_IMPLICIT) - { - /* - * Check the default policy, then rename the implicit printer to - * "AnyPrinter" or delete it... - */ - - if ((status = cupsdCheckPolicy(DefaultPolicyPtr, con, NULL)) != HTTP_OK) - { - send_http_error(con, status, NULL); - return; - } - - if (ImplicitAnyClasses) - { - snprintf(newname, sizeof(newname), "Any%s", resource + 10); - cupsdRenamePrinter(printer, newname); - } - else - cupsdDeletePrinter(printer, 1); - - /* - * Add the printer as a new local printer... - */ - - printer = cupsdAddPrinter(resource + 10); - modify = 0; - } - else if (printer->type & CUPS_PRINTER_DISCOVERED) - { - /* - * Check the default policy, then rename the remote printer to - * "Printer@server"... - */ - - if ((status = cupsdCheckPolicy(DefaultPolicyPtr, con, NULL)) != HTTP_OK) - { - send_http_error(con, status, NULL); - return; - } - - snprintf(newname, sizeof(newname), "%s@%s", resource + 10, - printer->hostname); - cupsdRenamePrinter(printer, newname); - - /* - * Add the printer as a new local printer... - */ - - printer = cupsdAddPrinter(resource + 10); - modify = 0; - } else if ((status = cupsdCheckPolicy(printer->op_policy_ptr, con, NULL)) != HTTP_OK) { @@ -4731,6 +4620,9 @@ check_quotas(cupsd_client_t *con, /* I - Client connection */ strlcpy(username, get_username(con), sizeof(username)); + if ((name = strchr(username, '@')) != NULL) + *name = '\0'; /* Strip @REALM */ + /* * Check global active job limits for printers and users... */ @@ -5048,192 +4940,6 @@ close_job(cupsd_client_t *con, /* I - Client connection */ } -/* - * 'copy_attribute()' - Copy a single attribute. - */ - -static ipp_attribute_t * /* O - New attribute */ -copy_attribute( - ipp_t *to, /* O - Destination request/response */ - ipp_attribute_t *attr, /* I - Attribute to copy */ - int quickcopy) /* I - Do a quick copy? */ -{ - int i; /* Looping var */ - ipp_attribute_t *toattr; /* Destination attribute */ - - - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "copy_attribute(%p, %p[%s,%x,%x])", to, attr, - attr->name ? attr->name : "(null)", attr->group_tag, - attr->value_tag); - - switch (attr->value_tag & ~IPP_TAG_COPY) - { - case IPP_TAG_ZERO : - toattr = ippAddSeparator(to); - break; - - case IPP_TAG_INTEGER : - case IPP_TAG_ENUM : - toattr = ippAddIntegers(to, attr->group_tag, attr->value_tag, - attr->name, attr->num_values, NULL); - - for (i = 0; i < attr->num_values; i ++) - toattr->values[i].integer = attr->values[i].integer; - break; - - case IPP_TAG_BOOLEAN : - toattr = ippAddBooleans(to, attr->group_tag, attr->name, - attr->num_values, NULL); - - for (i = 0; i < attr->num_values; i ++) - toattr->values[i].boolean = attr->values[i].boolean; - break; - - case IPP_TAG_STRING : - case IPP_TAG_TEXT : - case IPP_TAG_NAME : - case IPP_TAG_KEYWORD : - case IPP_TAG_URI : - case IPP_TAG_URISCHEME : - case IPP_TAG_CHARSET : - case IPP_TAG_LANGUAGE : - case IPP_TAG_MIMETYPE : - toattr = ippAddStrings(to, attr->group_tag, - (ipp_tag_t)(attr->value_tag | quickcopy), - attr->name, attr->num_values, NULL, NULL); - - if (quickcopy) - { - for (i = 0; i < attr->num_values; i ++) - toattr->values[i].string.text = attr->values[i].string.text; - } - else if (attr->value_tag & IPP_TAG_COPY) - { - for (i = 0; i < attr->num_values; i ++) - toattr->values[i].string.text = - _cupsStrAlloc(attr->values[i].string.text); - } - else - { - for (i = 0; i < attr->num_values; i ++) - toattr->values[i].string.text = - _cupsStrRetain(attr->values[i].string.text); - } - break; - - case IPP_TAG_DATE : - toattr = ippAddDate(to, attr->group_tag, attr->name, - attr->values[0].date); - break; - - case IPP_TAG_RESOLUTION : - toattr = ippAddResolutions(to, attr->group_tag, attr->name, - attr->num_values, IPP_RES_PER_INCH, - NULL, NULL); - - for (i = 0; i < attr->num_values; i ++) - { - toattr->values[i].resolution.xres = attr->values[i].resolution.xres; - toattr->values[i].resolution.yres = attr->values[i].resolution.yres; - toattr->values[i].resolution.units = attr->values[i].resolution.units; - } - break; - - case IPP_TAG_RANGE : - toattr = ippAddRanges(to, attr->group_tag, attr->name, - attr->num_values, NULL, NULL); - - for (i = 0; i < attr->num_values; i ++) - { - toattr->values[i].range.lower = attr->values[i].range.lower; - toattr->values[i].range.upper = attr->values[i].range.upper; - } - break; - - case IPP_TAG_TEXTLANG : - case IPP_TAG_NAMELANG : - toattr = ippAddStrings(to, attr->group_tag, - (ipp_tag_t)(attr->value_tag | quickcopy), - attr->name, attr->num_values, NULL, NULL); - - if (quickcopy) - { - for (i = 0; i < attr->num_values; i ++) - { - toattr->values[i].string.charset = attr->values[i].string.charset; - toattr->values[i].string.text = attr->values[i].string.text; - } - } - else if (attr->value_tag & IPP_TAG_COPY) - { - for (i = 0; i < attr->num_values; i ++) - { - if (!i) - toattr->values[i].string.charset = - _cupsStrAlloc(attr->values[i].string.charset); - else - toattr->values[i].string.charset = - toattr->values[0].string.charset; - - toattr->values[i].string.text = - _cupsStrAlloc(attr->values[i].string.text); - } - } - else - { - for (i = 0; i < attr->num_values; i ++) - { - if (!i) - toattr->values[i].string.charset = - _cupsStrRetain(attr->values[i].string.charset); - else - toattr->values[i].string.charset = - toattr->values[0].string.charset; - - toattr->values[i].string.text = - _cupsStrRetain(attr->values[i].string.text); - } - } - break; - - case IPP_TAG_BEGIN_COLLECTION : - toattr = ippAddCollections(to, attr->group_tag, attr->name, - attr->num_values, NULL); - - for (i = 0; i < attr->num_values; i ++) - { - toattr->values[i].collection = attr->values[i].collection; - attr->values[i].collection->use ++; - } - break; - - default : - toattr = ippAddIntegers(to, attr->group_tag, attr->value_tag, - attr->name, attr->num_values, NULL); - - for (i = 0; i < attr->num_values; i ++) - { - toattr->values[i].unknown.length = attr->values[i].unknown.length; - - if (toattr->values[i].unknown.length > 0) - { - if ((toattr->values[i].unknown.data = - malloc(toattr->values[i].unknown.length)) == NULL) - toattr->values[i].unknown.length = 0; - else - memcpy(toattr->values[i].unknown.data, - attr->values[i].unknown.data, - toattr->values[i].unknown.length); - } - } - break; /* anti-compiler-warning-code */ - } - - return (toattr); -} - - /* * 'copy_attrs()' - Copy attributes from one request to another. */ @@ -5301,7 +5007,7 @@ copy_attrs(ipp_t *to, /* I - Destination request */ !strcmp(fromattr->name, "media-col-database"))) continue; - copy_attribute(to, fromattr, quickcopy); + ippCopyAttribute(to, fromattr, quickcopy); } } } @@ -5983,8 +5689,8 @@ copy_job_attrs(cupsd_client_t *con, /* I - Client connection */ { httpAssembleURIf(HTTP_URI_CODING_ALL, job_uri, sizeof(job_uri), "ipp", NULL, con->servername, con->serverport, - job->dtype & (CUPS_PRINTER_IMPLICIT | CUPS_PRINTER_CLASS) ? - "/classes/%s" : "/printers/%s", + (job->dtype & CUPS_PRINTER_CLASS) ? "/classes/%s" : + "/printers/%s", job->dest); ippAddString(con->response, IPP_TAG_JOB, IPP_TAG_URI, "job-printer-uri", NULL, job_uri); @@ -6109,7 +5815,7 @@ copy_printer_attrs( "stop-printer" }; - if (printer->type & (CUPS_PRINTER_IMPLICIT | CUPS_PRINTER_CLASS)) + if (printer->type & CUPS_PRINTER_CLASS) ippAddString(con->response, IPP_TAG_PRINTER, IPP_TAG_NAME | IPP_TAG_COPY, "printer-error-policy-supported", NULL, "retry-current-job"); else @@ -6136,8 +5842,7 @@ copy_printer_attrs( ippAddBoolean(con->response, IPP_TAG_PRINTER, "printer-is-shared", printer->shared); - if ((!ra || cupsArrayFind(ra, "printer-more-info")) && - !(printer->type & CUPS_PRINTER_DISCOVERED)) + if (!ra || cupsArrayFind(ra, "printer-more-info")) { httpAssembleURIf(HTTP_URI_CODING_ALL, printer_uri, sizeof(printer_uri), "http", NULL, con->servername, con->serverport, @@ -6193,8 +5898,7 @@ copy_printer_attrs( ippAddInteger(con->response, IPP_TAG_PRINTER, IPP_TAG_INTEGER, "printer-up-time", curtime); - if ((!ra || cupsArrayFind(ra, "printer-uri-supported")) && - !(printer->type & CUPS_PRINTER_DISCOVERED)) + if (!ra || cupsArrayFind(ra, "printer-uri-supported")) { httpAssembleURIf(HTTP_URI_CODING_ALL, printer_uri, sizeof(printer_uri), "ipp", NULL, con->servername, con->serverport, @@ -8056,11 +7760,10 @@ get_ppd(cupsd_client_t *con, /* I - Client connection */ "printer-uri", NULL, dest->uri); return; } - else if (dtype & (CUPS_PRINTER_CLASS | CUPS_PRINTER_IMPLICIT)) + else if (dtype & CUPS_PRINTER_CLASS) { for (i = 0; i < dest->num_printers; i ++) - if (!(dest->printers[i]->type & - (CUPS_PRINTER_CLASS | CUPS_PRINTER_IMPLICIT))) + if (!(dest->printers[i]->type & CUPS_PRINTER_CLASS)) { snprintf(filename, sizeof(filename), "%s/ppd/%s.ppd", ServerRoot, dest->printers[i]->name); @@ -8507,15 +8210,6 @@ get_printers(cupsd_client_t *con, /* I - Client connection */ (!location || (printer->location && !_cups_strcasecmp(printer->location, location)))) { - /* - * If HideImplicitMembers is enabled, see if this printer or class - * is a member of an implicit class... - */ - - if (ImplicitClasses && HideImplicitMembers && - printer->in_implicit_class) - continue; - /* * If a username is specified, see if it is allowed or denied * access... @@ -9741,14 +9435,14 @@ read_job_ticket(cupsd_client_t *con) /* I - Client connection */ if (con->request->last == attr2) con->request->last = prev2; - _ippFreeAttr(attr2); + ippDeleteAttribute(NULL, attr2); } /* * Add new option by copying it... */ - copy_attribute(con->request, attr, 0); + ippCopyAttribute(con->request, attr, 0); } /* @@ -11027,7 +10721,7 @@ set_default(cupsd_client_t *con, /* I - Client connection */ "%s is now the default printer.", printer->name); cupsdMarkDirty(CUPSD_DIRTY_PRINTERS | CUPSD_DIRTY_CLASSES | - CUPSD_DIRTY_REMOTE | CUPSD_DIRTY_PRINTCAP); + CUPSD_DIRTY_PRINTCAP); cupsdLogMessage(CUPSD_LOG_INFO, "Default destination set to \"%s\" by \"%s\".", @@ -11205,9 +10899,8 @@ set_job_attrs(cupsd_client_t *con, /* I - Client connection */ send_ipp_status(con, IPP_ATTRIBUTES_NOT_SETTABLE, _("%s cannot be changed."), attr->name); - if ((attr2 = copy_attribute(con->response, attr, 0)) != NULL) - attr2->group_tag = IPP_TAG_UNSUPPORTED_GROUP; - + attr2 = ippCopyAttribute(con->response, attr, 0); + ippSetGroupTag(con->response, &attr2, IPP_TAG_UNSUPPORTED_GROUP); continue; } @@ -11221,8 +10914,8 @@ set_job_attrs(cupsd_client_t *con, /* I - Client connection */ { send_ipp_status(con, IPP_REQUEST_VALUE, _("Bad job-priority value.")); - if ((attr2 = copy_attribute(con->response, attr, 0)) != NULL) - attr2->group_tag = IPP_TAG_UNSUPPORTED_GROUP; + attr2 = ippCopyAttribute(con->response, attr, 0); + ippSetGroupTag(con->response, &attr2, IPP_TAG_UNSUPPORTED_GROUP); } else if (job->state_value >= IPP_JOB_PROCESSING) { @@ -11251,8 +10944,8 @@ set_job_attrs(cupsd_client_t *con, /* I - Client connection */ { send_ipp_status(con, IPP_REQUEST_VALUE, _("Bad job-state value.")); - if ((attr2 = copy_attribute(con->response, attr, 0)) != NULL) - attr2->group_tag = IPP_TAG_UNSUPPORTED_GROUP; + attr2 = ippCopyAttribute(con->response, attr, 0); + ippSetGroupTag(con->response, &attr2, IPP_TAG_UNSUPPORTED_GROUP); } else { @@ -11326,13 +11019,13 @@ set_job_attrs(cupsd_client_t *con, /* I - Client connection */ if (job->attrs->last == attr2) job->attrs->last = job->attrs->prev; - _ippFreeAttr(attr2); + ippDeleteAttribute(NULL, attr2); /* * Then copy the attribute... */ - copy_attribute(job->attrs, attr, 0); + ippCopyAttribute(job->attrs, attr, 0); /* * See if the job-name or job-hold-until is being changed. @@ -11373,7 +11066,7 @@ set_job_attrs(cupsd_client_t *con, /* I - Client connection */ if (attr2 == job->attrs->last) job->attrs->last = job->attrs->prev; - _ippFreeAttr(attr2); + ippDeleteAttribute(NULL, attr2); event |= CUPSD_EVENT_JOB_CONFIG_CHANGED; } @@ -11384,7 +11077,7 @@ set_job_attrs(cupsd_client_t *con, /* I - Client connection */ * Add new option by copying it... */ - copy_attribute(job->attrs, attr, 0); + ippCopyAttribute(job->attrs, attr, 0); event |= CUPSD_EVENT_JOB_CONFIG_CHANGED; } @@ -11649,7 +11342,7 @@ set_printer_defaults( continue; if (strcmp(attr->values[0].string.text, "retry-current-job") && - ((printer->type & (CUPS_PRINTER_IMPLICIT | CUPS_PRINTER_CLASS)) || + ((printer->type & CUPS_PRINTER_CLASS) || (strcmp(attr->values[0].string.text, "abort-job") && strcmp(attr->values[0].string.text, "retry-job") && strcmp(attr->values[0].string.text, "stop-printer")))) diff --git a/scheduler/job.c b/scheduler/job.c index 59e06dd55..b63eb36bd 100644 --- a/scheduler/job.c +++ b/scheduler/job.c @@ -362,8 +362,7 @@ cupsdCheckJobs(void) printer = cupsdFindDest(job->dest); pclass = NULL; - while (printer && - (printer->type & (CUPS_PRINTER_IMPLICIT | CUPS_PRINTER_CLASS))) + while (printer && (printer->type & CUPS_PRINTER_CLASS)) { /* * If the class is remote, just pass it to the remote server... @@ -415,10 +414,7 @@ cupsdCheckJobs(void) cupsdMarkDirty(CUPSD_DIRTY_JOBS); } - if ((!(printer->type & CUPS_PRINTER_DISCOVERED) && /* Printer is local */ - printer->state == IPP_PRINTER_IDLE) || /* and idle, OR */ - ((printer->type & CUPS_PRINTER_DISCOVERED) && /* Printer is remote */ - !printer->job)) /* and not printing */ + if (printer->state == IPP_PRINTER_IDLE) { /* * Start the job... @@ -748,7 +744,7 @@ cupsdContinueJob(cupsd_job_t *job) /* I - Job */ job->job_sheets->values[0].string.text, job->job_sheets->values[1].string.text); - if (job->printer->type & (CUPS_PRINTER_REMOTE | CUPS_PRINTER_IMPLICIT)) + if (job->printer->type & CUPS_PRINTER_REMOTE) banner_page = 0; else if (job->job_sheets == NULL) banner_page = 0; @@ -1006,7 +1002,7 @@ cupsdContinueJob(cupsd_job_t *job) /* I - Job */ envp[envc ++] = classification; } - if (job->dtype & (CUPS_PRINTER_CLASS | CUPS_PRINTER_IMPLICIT)) + if (job->dtype & CUPS_PRINTER_CLASS) { snprintf(class_name, sizeof(class_name), "CLASS=%s", job->dest); envp[envc ++] = class_name; @@ -1925,8 +1921,7 @@ cupsdMoveJob(cupsd_job_t *job, /* I - Job */ p->name); cupsdSetString(&job->dest, p->name); - job->dtype = p->type & (CUPS_PRINTER_CLASS | CUPS_PRINTER_REMOTE | - CUPS_PRINTER_IMPLICIT); + job->dtype = p->type & (CUPS_PRINTER_CLASS | CUPS_PRINTER_REMOTE); if ((attr = ippFindAttribute(job->attrs, "job-printer-uri", IPP_TAG_URI)) != NULL) @@ -2945,7 +2940,7 @@ finalize_job(cupsd_job_t *job, /* I - Job */ * act... */ - if (job->dtype & (CUPS_PRINTER_CLASS | CUPS_PRINTER_IMPLICIT)) + if (job->dtype & CUPS_PRINTER_CLASS) { /* * Queued on a class - mark the job as pending and we'll retry on @@ -4417,10 +4412,7 @@ update_job(cupsd_job_t *job) /* I - Job to check */ cupsdSetAuthInfoRequired(job->printer, attr, NULL); cupsdSetPrinterAttrs(job->printer); - if (job->printer->type & CUPS_PRINTER_DISCOVERED) - cupsdMarkDirty(CUPSD_DIRTY_REMOTE); - else - cupsdMarkDirty(CUPSD_DIRTY_PRINTERS); + cupsdMarkDirty(CUPSD_DIRTY_PRINTERS); } if ((attr = cupsGetOption("job-media-progress", num_attrs, diff --git a/scheduler/main.c b/scheduler/main.c index 0f4a711ea..7b7277175 100644 --- a/scheduler/main.c +++ b/scheduler/main.c @@ -766,11 +766,9 @@ main(int argc, /* I - Number of command-line args */ * inactivity... */ - if (timeout == 86400 && Launchd && LaunchdTimeout && !NumPolled && + if (timeout == 86400 && Launchd && LaunchdTimeout && !cupsArrayCount(ActiveJobs) && - (!Browsing || - (!BrowseRemoteProtocols && - (!BrowseLocalProtocols || !cupsArrayCount(Printers))))) + (!Browsing || !BrowseLocalProtocols || !cupsArrayCount(Printers))) { timeout = LaunchdTimeout; launchd_idle_exit = 1; @@ -812,8 +810,6 @@ main(int argc, /* I - Number of command-line args */ i ++, lis = (cupsd_listener_t *)cupsArrayNext(Listeners)) cupsdLogMessage(CUPSD_LOG_EMERG, "Listeners[%d] = %d", i, lis->fd); - cupsdLogMessage(CUPSD_LOG_EMERG, "BrowseSocket = %d", BrowseSocket); - cupsdLogMessage(CUPSD_LOG_EMERG, "CGIPipes[0] = %d", CGIPipes[0]); #ifdef __APPLE__ @@ -914,31 +910,6 @@ main(int argc, /* I - Number of command-line args */ expire_time = current_time; } - /* - * Update the browse list as needed... - */ - - if (Browsing) - { -#ifdef HAVE_LIBSLP - if ((BrowseRemoteProtocols & BROWSE_SLP) && - BrowseSLPRefresh <= current_time) - cupsdUpdateSLPBrowse(); -#endif /* HAVE_LIBSLP */ - -#ifdef HAVE_LDAP - if ((BrowseRemoteProtocols & BROWSE_LDAP) && - BrowseLDAPRefresh <= current_time) - cupsdUpdateLDAPBrowse(); -#endif /* HAVE_LDAP */ - } - - if (Browsing && current_time > browse_time) - { - cupsdSendBrowseList(); - browse_time = current_time; - } - #ifndef HAVE_AUTHORIZATION_H /* * Update the root certificate once every 5 minutes if we have client @@ -1031,8 +1002,6 @@ main(int argc, /* I - Number of command-line args */ cupsArrayCount(ActiveJobs)); cupsdLogMessage(CUPSD_LOG_DEBUG, "Report: printers=%d", cupsArrayCount(Printers)); - cupsdLogMessage(CUPSD_LOG_DEBUG, "Report: printers-implicit=%d", - cupsArrayCount(ImplicitPrinters)); string_count = _cupsStrStatistics(&alloc_bytes, &total_bytes); cupsdLogMessage(CUPSD_LOG_DEBUG, @@ -1512,10 +1481,8 @@ launchd_checkout(void) * shared printers to advertise... */ - if (cupsArrayCount(ActiveJobs) || NumPolled || - (Browsing && - (BrowseRemoteProtocols || - (BrowseLocalProtocols && cupsArrayCount(Printers))))) + if (cupsArrayCount(ActiveJobs) || + (Browsing && BrowseLocalProtocols && cupsArrayCount(Printers))) { cupsdLogMessage(CUPSD_LOG_DEBUG, "Creating launchd keepalive file \"" CUPS_KEEPALIVE @@ -1773,7 +1740,6 @@ select_timeout(int fds) /* I - Number of descriptors returned */ long timeout; /* Timeout for select */ time_t now; /* Current time */ cupsd_client_t *con; /* Client information */ - cupsd_printer_t *p; /* Printer information */ cupsd_job_t *job; /* Job information */ cupsd_subscription_t *sub; /* Subscription information */ const char *why; /* Debugging aid */ @@ -1847,54 +1813,6 @@ select_timeout(int fds) /* I - Number of descriptors returned */ why = "timeout a client connection"; } - /* - * Update the browse list as needed... - */ - - if (Browsing && BrowseLocalProtocols) - { -#ifdef HAVE_LIBSLP - if ((BrowseLocalProtocols & BROWSE_SLP) && (BrowseSLPRefresh < timeout)) - { - timeout = BrowseSLPRefresh; - why = "update SLP browsing"; - } -#endif /* HAVE_LIBSLP */ - -#ifdef HAVE_LDAP - if ((BrowseLocalProtocols & BROWSE_LDAP) && (BrowseLDAPRefresh < timeout)) - { - timeout = BrowseLDAPRefresh; - why = "update LDAP browsing"; - } -#endif /* HAVE_LDAP */ - - if ((BrowseLocalProtocols & BROWSE_CUPS) && NumBrowsers) - { - for (p = (cupsd_printer_t *)cupsArrayFirst(Printers); - p; - p = (cupsd_printer_t *)cupsArrayNext(Printers)) - { - if (p->type & CUPS_PRINTER_REMOTE) - { - if ((p->browse_time + BrowseTimeout) < timeout) - { - timeout = p->browse_time + BrowseTimeout; - why = "browse timeout a printer"; - } - } - else if (p->shared && !(p->type & CUPS_PRINTER_IMPLICIT)) - { - if (BrowseInterval && (p->browse_time + BrowseInterval) < timeout) - { - timeout = p->browse_time + BrowseInterval; - why = "send browse update"; - } - } - } - } - } - /* * Write out changes to configuration and state files... */ diff --git a/scheduler/printers.c b/scheduler/printers.c index 6e9705893..fd6216ba4 100644 --- a/scheduler/printers.c +++ b/scheduler/printers.c @@ -168,9 +168,6 @@ cupsdAddPrinter(const char *name) /* I - Name of printer */ "cupsdAddPrinter: Adding %s to Printers", p->name); cupsArrayAdd(Printers, p); - if (!ImplicitPrinters) - ImplicitPrinters = cupsArrayNew(compare_printers, NULL); - /* * Return the new printer... */ @@ -751,16 +748,6 @@ cupsdDeletePrinter( update ? "Job stopped due to printer being deleted." : "Job stopped."); - /* - * If this printer is the next for browsing, point to the next one... - */ - - if (p == BrowseNext) - { - cupsArrayFind(Printers, p); - BrowseNext = (cupsd_printer_t *)cupsArrayNext(Printers); - } - /* * Remove the printer from the list... */ @@ -769,14 +756,6 @@ cupsdDeletePrinter( "cupsdDeletePrinter: Removing %s from Printers", p->name); cupsArrayRemove(Printers, p); - if (p->type & CUPS_PRINTER_IMPLICIT) - { - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "cupsdDeletePrinter: Removing %s from ImplicitPrinters", - p->name); - cupsArrayRemove(ImplicitPrinters, p); - } - /* * Remove the dummy interface/icon/option files under IRIX... */ @@ -807,43 +786,19 @@ cupsdDeletePrinter( */ if (p == DefaultPrinter) - { DefaultPrinter = NULL; - if (UseNetworkDefault) - { - /* - * Find the first network default printer and use it... - */ - - cupsd_printer_t *dp; /* New default printer */ - - - for (dp = (cupsd_printer_t *)cupsArrayFirst(Printers); - dp; - dp = (cupsd_printer_t *)cupsArrayNext(Printers)) - if (dp != p && (dp->type & CUPS_PRINTER_DEFAULT)) - { - DefaultPrinter = dp; - break; - } - } - } - /* * Remove this printer from any classes... */ - if (!(p->type & CUPS_PRINTER_IMPLICIT)) - { - changed = cupsdDeletePrinterFromClasses(p); + changed = cupsdDeletePrinterFromClasses(p); - /* - * Deregister from any browse protocols... - */ + /* + * Deregister from any browse protocols... + */ - cupsdDeregisterPrinter(p, 1); - } + cupsdDeregisterPrinter(p, 1); /* * Free all memory used by the printer... @@ -889,9 +844,6 @@ cupsdDeletePrinter( cupsArrayDelete(p->filetypes); - if (p->browse_attrs) - free(p->browse_attrs); - cupsFreeOptions(p->num_options, p->options); free(p); @@ -1396,14 +1348,6 @@ cupsdRenamePrinter( "cupsdRenamePrinter: Removing %s from Printers", p->name); cupsArrayRemove(Printers, p); - if (p->type & CUPS_PRINTER_IMPLICIT) - { - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "cupsdRenamePrinter: Removing %s from ImplicitPrinters", - p->name); - cupsArrayRemove(ImplicitPrinters, p); - } - /* * Rename the printer type... */ @@ -1436,14 +1380,6 @@ cupsdRenamePrinter( cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdRenamePrinter: Adding %s to Printers", p->name); cupsArrayAdd(Printers, p); - - if (p->type & CUPS_PRINTER_IMPLICIT) - { - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "cupsdRenamePrinter: Adding %s to ImplicitPrinters", - p->name); - cupsArrayAdd(ImplicitPrinters, p); - } } @@ -1501,12 +1437,10 @@ cupsdSaveAllPrinters(void) printer = (cupsd_printer_t *)cupsArrayNext(Printers)) { /* - * Skip remote destinations and printer classes... + * Skip printer classes... */ - if ((printer->type & CUPS_PRINTER_DISCOVERED) || - (printer->type & CUPS_PRINTER_CLASS) || - (printer->type & CUPS_PRINTER_IMPLICIT)) + if (printer->type & CUPS_PRINTER_CLASS) continue; /* @@ -2106,8 +2040,7 @@ cupsdSetPrinterAttr( void cupsdSetPrinterAttrs(cupsd_printer_t *p)/* I - Printer to setup */ { - int i, /* Looping var */ - length; /* Length of browse attributes */ + int i; /* Looping var */ char resource[HTTP_MAX_URI]; /* Resource portion of URI */ int num_air; /* Number of auth-info-required values */ const char * const *air; /* auth-info-required values */ @@ -2115,7 +2048,6 @@ cupsdSetPrinterAttrs(cupsd_printer_t *p)/* I - Printer to setup */ const char *auth_supported; /* Authentication supported */ ipp_t *oldattrs; /* Old printer attributes */ ipp_attribute_t *attr; /* Attribute data */ - cups_option_t *option; /* Current printer option */ char *name, /* Current user/group name */ *filter; /* Current filter */ static const char * const air_none[] = @@ -2158,8 +2090,7 @@ cupsdSetPrinterAttrs(cupsd_printer_t *p)/* I - Printer to setup */ num_air = p->num_auth_info_required; air = p->auth_info_required; } - else if ((p->type & CUPS_PRINTER_AUTHENTICATED) && - (p->type & CUPS_PRINTER_DISCOVERED)) + else if (p->type & CUPS_PRINTER_AUTHENTICATED) { num_air = 2; air = air_userpass; @@ -2191,15 +2122,12 @@ cupsdSetPrinterAttrs(cupsd_printer_t *p)/* I - Printer to setup */ auth_supported = "negotiate"; #endif /* HAVE_GSSAPI */ - if (!(p->type & CUPS_PRINTER_DISCOVERED)) - { - if (auth_type != CUPSD_AUTH_NONE) - p->type |= CUPS_PRINTER_AUTHENTICATED; - else - p->type &= ~CUPS_PRINTER_AUTHENTICATED; - } + if (auth_type != CUPSD_AUTH_NONE) + p->type |= CUPS_PRINTER_AUTHENTICATED; + else + p->type &= ~CUPS_PRINTER_AUTHENTICATED; } - else if (!(p->type & CUPS_PRINTER_DISCOVERED)) + else p->type &= ~CUPS_PRINTER_AUTHENTICATED; /* @@ -2248,7 +2176,7 @@ cupsdSetPrinterAttrs(cupsd_printer_t *p)/* I - Printer to setup */ ippAddStrings(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "auth-info-required", num_air, NULL, air); - if (cupsArrayCount(Banners) > 0 && !(p->type & CUPS_PRINTER_DISCOVERED)) + if (cupsArrayCount(Banners) > 0) { /* * Setup the job-sheets-default attribute... @@ -2269,164 +2197,117 @@ cupsdSetPrinterAttrs(cupsd_printer_t *p)/* I - Printer to setup */ p->raw = 0; p->remote = 0; - if (p->type & CUPS_PRINTER_DISCOVERED) + /* + * Assign additional attributes depending on whether this is a printer + * or class... + */ + + if (p->type & CUPS_PRINTER_CLASS) { + p->raw = 1; + p->type &= ~CUPS_PRINTER_OPTIONS; + /* - * Tell the client this is a remote printer of some type... + * Add class-specific attributes... */ - if (strchr(p->uri, '?')) + ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_TEXT, + "printer-make-and-model", NULL, "Local Printer Class"); + ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_URI, "device-uri", NULL, + "file:///dev/null"); + + if (p->num_printers > 0) { /* - * Strip trailing "?options" from URI... + * Add a list of member names; URIs are added in copy_printer_attrs... */ - char *ptr; /* Pointer into URI */ + attr = ippAddStrings(p->attrs, IPP_TAG_PRINTER, IPP_TAG_NAME, + "member-names", p->num_printers, NULL, NULL); + p->type |= CUPS_PRINTER_OPTIONS; - strlcpy(resource, p->uri, sizeof(resource)); - if ((ptr = strchr(resource, '?')) != NULL) - *ptr = '\0'; + for (i = 0; i < p->num_printers; i ++) + { + if (attr != NULL) + attr->values[i].string.text = _cupsStrRetain(p->printers[i]->name); - ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_URI, - "printer-uri-supported", NULL, resource); + p->type &= ~CUPS_PRINTER_OPTIONS | p->printers[i]->type; + } } - else - ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_URI, - "printer-uri-supported", NULL, p->uri); - - ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_URI, "printer-more-info", - NULL, p->uri); - - if (p->make_model) - ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_TEXT, - "printer-make-and-model", NULL, p->make_model); - - ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_URI, "device-uri", NULL, - p->uri); - - p->raw = 1; - p->remote = 1; } else { /* - * Assign additional attributes depending on whether this is a printer - * or class... + * Add printer-specific attributes... */ - if (p->type & (CUPS_PRINTER_CLASS | CUPS_PRINTER_IMPLICIT)) - { - p->raw = 1; - p->type &= ~CUPS_PRINTER_OPTIONS; - - /* - * Add class-specific attributes... - */ - - if ((p->type & CUPS_PRINTER_IMPLICIT) && p->num_printers > 0 && - p->printers[0]->make_model) - ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_TEXT, - "printer-make-and-model", NULL, p->printers[0]->make_model); - else - ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_TEXT, - "printer-make-and-model", NULL, "Local Printer Class"); + ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_URI, "device-uri", NULL, + p->sanitized_device_uri); - ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_URI, "device-uri", NULL, - "file:///dev/null"); + /* + * Assign additional attributes from the PPD file (if any)... + */ - if (p->num_printers > 0) - { - /* - * Add a list of member names; URIs are added in copy_printer_attrs... - */ + load_ppd(p); - attr = ippAddStrings(p->attrs, IPP_TAG_PRINTER, IPP_TAG_NAME, - "member-names", p->num_printers, NULL, NULL); - p->type |= CUPS_PRINTER_OPTIONS; + /* + * Add filters for printer... + */ - for (i = 0; i < p->num_printers; i ++) - { - if (attr != NULL) - attr->values[i].string.text = _cupsStrRetain(p->printers[i]->name); + cupsdSetPrinterReasons(p, "-cups-missing-filter-warning," + "cups-insecure-filter-warning"); - p->type &= ~CUPS_PRINTER_OPTIONS | p->printers[i]->type; - } - } + if (p->pc && p->pc->filters) + { + for (filter = (char *)cupsArrayFirst(p->pc->filters); + filter; + filter = (char *)cupsArrayNext(p->pc->filters)) + add_printer_filter(p, p->filetype, filter); } - else + else if (!(p->type & CUPS_PRINTER_REMOTE)) { - /* - * Add printer-specific attributes... - */ + char interface[1024]; /* Interface script */ - ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_URI, "device-uri", NULL, - p->sanitized_device_uri); - /* - * Assign additional attributes from the PPD file (if any)... - */ - - load_ppd(p); - - /* - * Add filters for printer... - */ - - cupsdSetPrinterReasons(p, "-cups-missing-filter-warning," - "cups-insecure-filter-warning"); - - if (p->pc && p->pc->filters) + snprintf(interface, sizeof(interface), "%s/interfaces/%s", ServerRoot, + p->name); + if (!access(interface, X_OK)) { - for (filter = (char *)cupsArrayFirst(p->pc->filters); - filter; - filter = (char *)cupsArrayNext(p->pc->filters)) - add_printer_filter(p, p->filetype, filter); + /* + * Yes, we have a System V style interface script; use it! + */ + + snprintf(interface, sizeof(interface), "*/* 0 %s/interfaces/%s", + ServerRoot, p->name); + add_printer_filter(p, p->filetype, interface); } - else if (!(p->type & CUPS_PRINTER_REMOTE)) + else { - char interface[1024]; /* Interface script */ - - - snprintf(interface, sizeof(interface), "%s/interfaces/%s", ServerRoot, - p->name); - if (!access(interface, X_OK)) - { - /* - * Yes, we have a System V style interface script; use it! - */ - - snprintf(interface, sizeof(interface), "*/* 0 %s/interfaces/%s", - ServerRoot, p->name); - add_printer_filter(p, p->filetype, interface); - } - else - { - /* - * Add a filter from application/vnd.cups-raw to printer/name to - * handle "raw" printing by users. - */ + /* + * Add a filter from application/vnd.cups-raw to printer/name to + * handle "raw" printing by users. + */ - add_printer_filter(p, p->filetype, "application/vnd.cups-raw 0 -"); + add_printer_filter(p, p->filetype, "application/vnd.cups-raw 0 -"); - /* - * Add a PostScript filter, since this is still possibly PS printer. - */ + /* + * Add a PostScript filter, since this is still possibly PS printer. + */ - add_printer_filter(p, p->filetype, - "application/vnd.cups-postscript 0 -"); - } + add_printer_filter(p, p->filetype, + "application/vnd.cups-postscript 0 -"); } + } - if (p->pc && p->pc->prefilters) - { - if (!p->prefiltertype) - p->prefiltertype = mimeAddType(MimeDatabase, "prefilter", p->name); + if (p->pc && p->pc->prefilters) + { + if (!p->prefiltertype) + p->prefiltertype = mimeAddType(MimeDatabase, "prefilter", p->name); - for (filter = (char *)cupsArrayFirst(p->pc->prefilters); - filter; - filter = (char *)cupsArrayNext(p->pc->prefilters)) - add_printer_filter(p, p->prefiltertype, filter); - } + for (filter = (char *)cupsArrayFirst(p->pc->prefilters); + filter; + filter = (char *)cupsArrayNext(p->pc->prefilters)) + add_printer_filter(p, p->prefiltertype, filter); } } @@ -2526,98 +2407,8 @@ cupsdSetPrinterAttrs(cupsd_printer_t *p)/* I - Printer to setup */ * Force sharing off for remote queues... */ - if (p->type & (CUPS_PRINTER_REMOTE | CUPS_PRINTER_IMPLICIT)) + if (p->type & CUPS_PRINTER_REMOTE) p->shared = 0; - else - { - /* - * Copy the printer options into a browse attributes string we can re-use. - */ - - const char *valptr; /* Pointer into value */ - char *attrptr; /* Pointer into attribute string */ - - - /* - * Free the old browse attributes as needed... - */ - - if (p->browse_attrs) - free(p->browse_attrs); - - /* - * Compute the length of all attributes + job-sheets, lease-duration, - * and BrowseLocalOptions. - */ - - for (length = 1, i = p->num_options, option = p->options; - i > 0; - i --, option ++) - { - length += strlen(option->name) + 2; - - if (option->value) - { - for (valptr = option->value; *valptr; valptr ++) - if (strchr(" \"\'\\", *valptr)) - length += 2; - else - length ++; - } - } - - length += 13 + strlen(p->job_sheets[0]) + strlen(p->job_sheets[1]); - length += 32; - if (BrowseLocalOptions) - length += 12 + strlen(BrowseLocalOptions); - - /* - * Allocate the new string... - */ - - if ((p->browse_attrs = calloc(1, length)) == NULL) - cupsdLogMessage(CUPSD_LOG_ERROR, - "Unable to allocate %d bytes for browse data!", - length); - else - { - /* - * Got the allocated string, now copy the options and attributes over... - */ - - sprintf(p->browse_attrs, "job-sheets=%s,%s lease-duration=%d", - p->job_sheets[0], p->job_sheets[1], BrowseTimeout); - attrptr = p->browse_attrs + strlen(p->browse_attrs); - - if (BrowseLocalOptions) - { - sprintf(attrptr, " ipp-options=%s", BrowseLocalOptions); - attrptr += strlen(attrptr); - } - - for (i = p->num_options, option = p->options; - i > 0; - i --, option ++) - { - *attrptr++ = ' '; - strcpy(attrptr, option->name); - attrptr += strlen(attrptr); - - if (option->value) - { - *attrptr++ = '='; - - for (valptr = option->value; *valptr; valptr ++) - { - if (strchr(" \"\'\\", *valptr)) - *attrptr++ = '\\'; - - *attrptr++ = *valptr; - } - } - } - } - } /* * Populate the document-format-supported attribute... @@ -2809,13 +2600,6 @@ cupsdSetPrinterState( }; - /* - * Can't set status of remote printers... - */ - - if (p->type & CUPS_PRINTER_DISCOVERED) - return; - /* * Set the new state... */ @@ -2835,9 +2619,7 @@ cupsdSetPrinterState( * Let the browse code know this needs to be updated... */ - BrowseNext = p; - p->state_time = time(NULL); - p->browse_time = 0; + p->state_time = time(NULL); #ifdef __sgi write_irix_state(p); @@ -3035,22 +2817,6 @@ cupsdUpdatePrinters(void) p; p = (cupsd_printer_t *)cupsArrayNext(Printers)) { - /* - * Remove remote printers if we are no longer browsing... - */ - - if (!Browsing && - (p->type & (CUPS_PRINTER_IMPLICIT | CUPS_PRINTER_DISCOVERED))) - { - if (p->type & CUPS_PRINTER_IMPLICIT) - cupsArrayRemove(ImplicitPrinters, p); - - cupsArraySave(Printers); - cupsdDeletePrinter(p, 0); - cupsArrayRestore(Printers); - continue; - } - /* * Update the operation policy pointer... */ @@ -3059,11 +2825,10 @@ cupsdUpdatePrinters(void) p->op_policy_ptr = DefaultPolicyPtr; /* - * Update printer attributes as needed... + * Update printer attributes... */ - if (!(p->type & CUPS_PRINTER_DISCOVERED)) - cupsdSetPrinterAttrs(p); + cupsdSetPrinterAttrs(p); } } @@ -3156,8 +2921,7 @@ cupsdValidateDest( *printer = p; if (dtype) - *dtype = p->type & (CUPS_PRINTER_CLASS | CUPS_PRINTER_IMPLICIT | - CUPS_PRINTER_REMOTE | CUPS_PRINTER_DISCOVERED); + *dtype = p->type & (CUPS_PRINTER_CLASS | CUPS_PRINTER_REMOTE); return (p->name); } @@ -3215,8 +2979,7 @@ cupsdValidateDest( *printer = p; if (dtype) - *dtype = p->type & (CUPS_PRINTER_CLASS | CUPS_PRINTER_IMPLICIT | - CUPS_PRINTER_REMOTE | CUPS_PRINTER_DISCOVERED); + *dtype = p->type & (CUPS_PRINTER_CLASS | CUPS_PRINTER_REMOTE); return (p->name); } @@ -3899,9 +3662,7 @@ delete_printer_filters( static void dirty_printer(cupsd_printer_t *p) /* I - Printer */ { - if (p->type & CUPS_PRINTER_DISCOVERED) - cupsdMarkDirty(CUPSD_DIRTY_REMOTE); - else if (p->type & CUPS_PRINTER_CLASS) + if (p->type & CUPS_PRINTER_CLASS) cupsdMarkDirty(CUPSD_DIRTY_CLASSES); else cupsdMarkDirty(CUPSD_DIRTY_PRINTERS); @@ -3941,7 +3702,7 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */ _pwg_map_t *pwgsource, /* Current PWG source */ *pwgtype; /* Current PWG type */ ipp_attribute_t *attr; /* Attribute data */ - ipp_value_t *val; /* Attribute value */ + _ipp_value_t *val; /* Attribute value */ int num_finishings, /* Number of finishings */ finishings[5]; /* finishings-supported values */ int num_qualities, /* Number of print-quality values */ diff --git a/scheduler/printers.h b/scheduler/printers.h index 7c8ecabbd..41ae3b3f9 100644 --- a/scheduler/printers.h +++ b/scheduler/printers.h @@ -61,9 +61,6 @@ struct cupsd_printer_s time_t state_time; /* Time at this state */ char *job_sheets[2]; /* Banners/job sheets */ cups_ptype_t type; /* Printer type (color, small, etc.) */ - char *browse_attrs; /* Attributes sent with browse data */ - time_t browse_expire; /* Expiration time for printer */ - time_t browse_time; /* Last time update was sent/received */ char *device_uri; /* Device URI */ char *sanitized_device_uri; /* Sanitized device URI */ char *port_monitor; /* Port monitor */ @@ -116,10 +113,8 @@ VAR ipp_t *CommonData VALUE(NULL); /* Common printer object attrs */ VAR cups_array_t *CommonDefaults VALUE(NULL); /* Common -default option names */ -VAR cups_array_t *Printers VALUE(NULL), +VAR cups_array_t *Printers VALUE(NULL); /* Printer list */ - *ImplicitPrinters VALUE(NULL); - /* Implicit class printers */ VAR cupsd_printer_t *DefaultPrinter VALUE(NULL); /* Default printer */ VAR char *DefaultPolicy VALUE(NULL); diff --git a/scheduler/server.c b/scheduler/server.c index da98ffaa1..454a898f5 100644 --- a/scheduler/server.c +++ b/scheduler/server.c @@ -56,7 +56,6 @@ cupsdStartServer(void) cupsdStartListening(); cupsdStartBrowsing(); - cupsdStartPolling(); /* * Create a pipe for CGI processes... @@ -100,7 +99,6 @@ cupsdStopServer(void) cupsdCloseAllClients(); cupsdStopListening(); - cupsdStopPolling(); cupsdStopBrowsing(); cupsdStopAllNotifiers(); cupsdDeleteAllCerts(); diff --git a/scheduler/sysman.c b/scheduler/sysman.c index 0bab71727..c57d6e4fb 100644 --- a/scheduler/sysman.c +++ b/scheduler/sysman.c @@ -87,9 +87,6 @@ cupsdCleanDirty(void) if (DirtyFiles & CUPSD_DIRTY_CLASSES) cupsdSaveAllClasses(); - if (DirtyFiles & CUPSD_DIRTY_REMOTE) - cupsdSaveRemoteCache(); - if (DirtyFiles & CUPSD_DIRTY_PRINTCAP) cupsdWritePrintcap(); @@ -123,10 +120,9 @@ cupsdCleanDirty(void) void cupsdMarkDirty(int what) /* I - What file(s) are dirty? */ { - cupsdLogMessage(CUPSD_LOG_DEBUG, "cupsdMarkDirty(%c%c%c%c%c%c)", + cupsdLogMessage(CUPSD_LOG_DEBUG, "cupsdMarkDirty(%c%c%c%c%c)", (what & CUPSD_DIRTY_PRINTERS) ? 'P' : '-', (what & CUPSD_DIRTY_CLASSES) ? 'C' : '-', - (what & CUPSD_DIRTY_REMOTE) ? 'R' : '-', (what & CUPSD_DIRTY_PRINTCAP) ? 'p' : '-', (what & CUPSD_DIRTY_JOBS) ? 'J' : '-', (what & CUPSD_DIRTY_SUBSCRIPTIONS) ? 'S' : '-'); @@ -266,8 +262,8 @@ cupsdSetBusyState(void) # define SYSEVENT_NAMECHANGED 0x10 /* Computer name changed */ -/* - * Structures... +/* + * Structures... */ typedef struct cupsd_sysevent_s /*** System event data ****/ @@ -286,14 +282,14 @@ typedef struct cupsd_thread_data_s /*** Thread context data ****/ } cupsd_thread_data_t; -/* - * Local globals... +/* + * Local globals... */ static pthread_t SysEventThread = NULL; /* Thread to host a runloop */ static pthread_mutex_t SysEventThreadMutex = { 0 }; - /* Coordinates access to shared gloabals */ + /* Coordinates access to shared gloabals */ static pthread_cond_t SysEventThreadCond = { 0 }; /* Thread initialization complete condition */ static CFRunLoopRef SysEventRunloop = NULL; @@ -316,8 +312,8 @@ static CFStringRef ComputerNameKey = NULL, static cupsd_sysevent_t LastSysEvent; /* Last system event (for delayed sleep) */ -/* - * Local functions... +/* + * Local functions... */ static void *sysEventThreadEntry(void); @@ -499,8 +495,8 @@ sysEventThreadEntry(void) kSCEntNetIPv6); if (!NetworkGlobalKeyDNS) - NetworkGlobalKeyDNS = - SCDynamicStoreKeyCreateNetworkGlobalEntity(kCFAllocatorDefault, + NetworkGlobalKeyDNS = + SCDynamicStoreKeyCreateNetworkGlobalEntity(kCFAllocatorDefault, kSCDynamicStoreDomainState, kSCEntNetDNS); @@ -582,7 +578,7 @@ sysEventThreadEntry(void) threadData.timerRef = CFRunLoopTimerCreate(kCFAllocatorDefault, - CFAbsoluteTimeGetCurrent() + (86400L * 365L * 10L), + CFAbsoluteTimeGetCurrent() + (86400L * 365L * 10L), 86400L * 365L * 10L, 0, 0, sysEventTimerNotifier, &timerContext); CFRunLoopAddTimer(CFRunLoopGetCurrent(), threadData.timerRef, @@ -674,7 +670,7 @@ sysEventPowerNotifier( break; case kIOMessageSystemHasPoweredOn: - /* + /* * Because powered on is followed by a net-changed event, delay * before sending it. */ @@ -702,7 +698,7 @@ sysEventPowerNotifier( if (sendit == 1) { - /* + /* * Send the event to the main thread now. */ @@ -712,7 +708,7 @@ sysEventPowerNotifier( } else { - /* + /* * Send the event to the main thread after 1 to 2 seconds. */ @@ -738,7 +734,7 @@ sysEventConfigurationNotifier( threadData = (cupsd_thread_data_t *)context; - + (void)store; /* anti-compiler-warning-code */ CFRange range = CFRangeMake(0, CFArrayGetCount(changedKeys)); @@ -758,12 +754,12 @@ sysEventConfigurationNotifier( } /* - * Because we registered for several different kinds of change notifications - * this callback usually gets called several times in a row. We use a timer to + * Because we registered for several different kinds of change notifications + * this callback usually gets called several times in a row. We use a timer to * de-bounce these so we only end up generating one event for the main thread. */ - CFRunLoopTimerSetNextFireDate(threadData->timerRef, + CFRunLoopTimerSetNextFireDate(threadData->timerRef, CFAbsoluteTimeGetCurrent() + 5); } @@ -865,20 +861,9 @@ sysUpdate(void) p; p = (cupsd_printer_t *)cupsArrayNext(Printers)) { - if (p->type & CUPS_PRINTER_DISCOVERED) - { - cupsdLogMessage(CUPSD_LOG_DEBUG, - "Deleting remote destination \"%s\"", p->name); - cupsArraySave(Printers); - cupsdDeletePrinter(p, 0); - cupsArrayRestore(Printers); - } - else - { - cupsdLogMessage(CUPSD_LOG_DEBUG, - "Deregistering local printer \"%s\"", p->name); - cupsdDeregisterPrinter(p, 0); - } + cupsdLogMessage(CUPSD_LOG_DEBUG, + "Deregistering local printer \"%s\"", p->name); + cupsdDeregisterPrinter(p, 0); } cupsdCleanDirty(); @@ -950,23 +935,8 @@ sysUpdate(void) if (sysevent.event & SYSEVENT_NETCHANGED) { if (!Sleeping) - { cupsdLogMessage(CUPSD_LOG_DEBUG, "System network configuration changed"); - - /* - * Resetting browse_time before calling cupsdSendBrowseList causes - * browse packets to be sent for local shared printers. - */ - - for (p = (cupsd_printer_t *)cupsArrayFirst(Printers); - p; - p = (cupsd_printer_t *)cupsArrayNext(Printers)) - p->browse_time = 0; - - cupsdSendBrowseList(); - cupsdRestartPolling(); - } else cupsdLogMessage(CUPSD_LOG_DEBUG, "System network configuration changed; " @@ -1002,10 +972,7 @@ sysUpdate(void) for (p = (cupsd_printer_t *)cupsArrayFirst(Printers); p; p = (cupsd_printer_t *)cupsArrayNext(Printers)) - { - p->browse_time = 0; cupsdRegisterPrinter(p); - } } else cupsdLogMessage(CUPSD_LOG_DEBUG, diff --git a/scheduler/sysman.h b/scheduler/sysman.h index 0983f109d..d1672bf32 100644 --- a/scheduler/sysman.h +++ b/scheduler/sysman.h @@ -3,7 +3,7 @@ * * System management definitions for the CUPS scheduler. * - * Copyright 2007-2010 by Apple Inc. + * Copyright 2007-2011 by Apple Inc. * Copyright 2006 by Easy Software Products. * * These coded instructions, statements, and computer programs are the @@ -20,10 +20,10 @@ #define CUPSD_DIRTY_NONE 0 /* Nothing is dirty */ #define CUPSD_DIRTY_PRINTERS 1 /* printers.conf is dirty */ #define CUPSD_DIRTY_CLASSES 2 /* classes.conf is dirty */ -#define CUPSD_DIRTY_REMOTE 4 /* remote.cache is dirty */ -#define CUPSD_DIRTY_PRINTCAP 8 /* printcap is dirty */ -#define CUPSD_DIRTY_JOBS 16 /* jobs.cache or "c" file(s) are dirty */ -#define CUPSD_DIRTY_SUBSCRIPTIONS 32 /* subscriptions.conf is dirty */ +#define CUPSD_DIRTY_PRINTCAP 4 /* printcap is dirty */ +#define CUPSD_DIRTY_JOBS 8 /* jobs.cache or "c" file(s) are dirty */ +#define CUPSD_DIRTY_SUBSCRIPTIONS 16 /* subscriptions.conf is dirty */ + /* * Globals... diff --git a/scheduler/testdirsvc.c b/scheduler/testdirsvc.c deleted file mode 100644 index 88046a95c..000000000 --- a/scheduler/testdirsvc.c +++ /dev/null @@ -1,324 +0,0 @@ -/* - * "$Id: testdirsvc.c 6649 2007-07-11 21:46:42Z mike $" - * - * Browsing test program for CUPS. - * - * Copyright 2007-2011 by Apple Inc. - * Copyright 1997-2007 by Easy Software Products, all rights reserved. - * - * These coded instructions, statements, and computer programs are the - * property of Apple Inc. and are protected by Federal copyright - * law. Distribution and use rights are outlined in the file "LICENSE.txt" - * which should have been included with this file. If this file is - * file is missing or damaged, see the license at "http://www.cups.org/". - * - * Contents: - * - * main() - Simulate one or more remote printers. - * usage() - Show program usage... - */ - -/* - * Include necessary headers... - */ - -#include -#include - - -/* - * Local functions... - */ - -static void usage(void) __attribute__((noreturn)); - - -/* - * 'main()' - Simulate one or more remote printers. - */ - -int /* O - Exit status */ -main(int argc, /* I - Number of command-line arguments */ - char *argv[]) /* I - Command-line arguments */ -{ - int i, /* Looping var */ - printer, /* Current printer */ - num_printers, /* Number of printers */ - pclass, /* Current printer class */ - num_pclasses, /* Number of printer classes */ - server, /* Current server */ - num_servers, /* Number of servers */ - count, /* Number of printers sent this cycle */ - interval, /* Browse Interval */ - lease, /* Browse lease-duration */ - continuous, /* Run continuously? */ - port, /* Browse port */ - sock, /* Browse socket */ - val, /* Socket option value */ - seconds, /* Seconds until next cycle */ - verbose; /* Verbose output? */ - const char *options; /* Options for URIs */ - time_t curtime; /* Current UNIX time */ - struct tm *curdate; /* Current date and time */ - struct sockaddr_in addr; /* Broadcast address */ - char packet[1540]; /* Data packet */ - static const char * const names[26] = /* Printer names */ - { - "alpha", - "bravo", - "charlie", - "delta", - "echo", - "foxtrot", - "golf", - "hotel", - "india", - "juliet", - "kilo", - "lima", - "mike", - "november", - "oscar", - "papa", - "quebec", - "romeo", - "sierra", - "tango", - "uniform", - "victor", - "wiskey", - "x-ray", - "yankee", - "zulu" - }; - - - /* - * Process command-line arguments... - */ - - num_printers = 10; - num_pclasses = 5; - num_servers = 1; - interval = 30; - lease = 60; - port = 0; - verbose = 0; - continuous = 0; - options = NULL; - - for (i = 1; i < argc; i ++) - { - if (!strcmp(argv[i], "-c")) - continuous = 1; - else if (!strcmp(argv[i], "-i")) - { - i ++; - if (i < argc) - interval = atoi(argv[i]); - else - usage(); - - continuous = 1; - } - else if (!strcmp(argv[i], "-l")) - { - i ++; - if (i < argc) - lease = atoi(argv[i]); - else - usage(); - } - else if (!strcmp(argv[i], "-o")) - { - i ++; - if (i < argc) - options = argv[i]; - else - usage(); - } - else if (!strcmp(argv[i], "-C")) - { - i ++; - if (i < argc) - num_pclasses = atoi(argv[i]); - else - usage(); - } - else if (!strcmp(argv[i], "-p")) - { - i ++; - if (i < argc) - num_printers = atoi(argv[i]); - else - usage(); - } - else if (!strcmp(argv[i], "-s")) - { - i ++; - if (i < argc) - num_servers = atoi(argv[i]); - else - usage(); - } - else if (!strcmp(argv[i], "-v")) - verbose = 1; - else if (isdigit(argv[i][0] & 255)) - { - port = atoi(argv[i]); - } - else - usage(); - } - - if ((num_printers <= 0 && num_pclasses <= 0) || num_servers <= 0 || - interval <= 0 || lease < 1 || port <= 0) - usage(); - - /* - * Open a broadcast socket... - */ - - if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) - { - perror("Unable to open broadcast socket"); - return (1); - } - - /* - * Set the "broadcast" flag... - */ - - val = 1; - if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &val, sizeof(val))) - { - perror("Unable to put socket in broadcast mode"); - - close(sock); - return (1); - } - - /* - * Broadcast to 127.0.0.1 (localhost) - */ - - memset(&addr, 0, sizeof(addr)); - addr.sin_addr.s_addr = htonl(0x7f000001); - addr.sin_family = AF_INET; - addr.sin_port = htons(port); - - /* - * Send virtual printers continuously until we are stopped. - */ - - for (;;) - { - /* - * Start a new cycle of N printers... - */ - - printf("Sending %d printers from %d servers...\n", num_printers, - num_servers); - - count = num_servers * (num_printers + num_pclasses) / interval + 1; - curtime = time(NULL); - curdate = localtime(&curtime); - seconds = interval; - - for (i = 0, printer = 0; printer < num_printers; printer ++) - { - for (server = 0; server < num_servers; server ++, i ++) - { - if (i == count) - { - seconds --; - i = 0; - sleep(1); - curtime = time(NULL); - curdate = localtime(&curtime); - } - - snprintf(packet, sizeof(packet), - "%x %x ipp://testserver-%d/printers/%s-%d \"Server Room %d\" " - "\"Test Printer %d\" \"Acme Blazer 2000\"%s%s " - "lease-duration=%d\n", - CUPS_PRINTER_REMOTE, IPP_PRINTER_IDLE, server + 1, - names[printer % 26], printer / 26 + 1, server + 1, - printer + 1, options ? " ipp-options=" : "", - options ? options : "", lease); - - if (verbose) - printf("[%02d:%02d:%02d] %s", curdate->tm_hour, curdate->tm_min, - curdate->tm_sec, packet); - - if (sendto(sock, packet, strlen(packet), 0, - (struct sockaddr *)&addr, sizeof(addr)) < 0) - perror("Unabled to send packet"); - } - } - - - for (i = 0, pclass = 0; pclass < num_pclasses; pclass ++) - { - for (server = 0; server < num_servers; server ++, i ++) - { - if (i == count) - { - seconds --; - i = 0; - sleep(1); - curtime = time(NULL); - curdate = localtime(&curtime); - } - - snprintf(packet, sizeof(packet), - "%x %x ipp://testserver-%d/classes/class-%s-%d \"Server Room %d\" " - "\"Test Class %d\" \"Acme Blazer 2000\"%s%s " - "lease-duration=%d\n", - CUPS_PRINTER_REMOTE | CUPS_PRINTER_CLASS, IPP_PRINTER_IDLE, - server + 1, names[pclass % 26], pclass / 26 + 1, server + 1, - pclass + 1, options ? " ipp-options=" : "", - options ? options : "", lease); - - if (verbose) - printf("[%02d:%02d:%02d] %s", curdate->tm_hour, curdate->tm_min, - curdate->tm_sec, packet); - - if (sendto(sock, packet, strlen(packet), 0, - (struct sockaddr *)&addr, sizeof(addr)) < 0) - perror("Unabled to send packet"); - } - } - - if (!continuous) - break; - - /* - * Sleep for any remaining time... - */ - - if (seconds > 0) - sleep(seconds); - } - - return (0); -} - - -/* - * 'usage()' - Show program usage... - */ - -static void -usage(void) -{ - puts("Usage: testdirsvc [-c] [-i interval] [-l lease-duration] " - "[-o ipp-options] [-p printers] " - "[-C classes] [-s servers] [-v] port"); - exit(0); -} - - -/* - * End of "$Id: testdirsvc.c 6649 2007-07-11 21:46:42Z mike $". - */ diff --git a/scheduler/testsub.c b/scheduler/testsub.c index 8726774cb..36e161507 100644 --- a/scheduler/testsub.c +++ b/scheduler/testsub.c @@ -3,7 +3,7 @@ * * Scheduler notification tester for CUPS. * - * Copyright 2007-2010 by Apple Inc. + * Copyright 2007-2011 by Apple Inc. * Copyright 2006-2007 by Easy Software Products. * * These coded instructions, statements, and computer programs are the @@ -28,6 +28,7 @@ #include #include #include +#include /* TODO: Update so we don't need this */ /* @@ -302,7 +303,7 @@ print_attributes(ipp_t *ipp, /* I - IPP request */ int i; /* Looping var */ ipp_tag_t group; /* Current group */ ipp_attribute_t *attr; /* Current attribute */ - ipp_value_t *val; /* Current value */ + _ipp_value_t *val; /* Current value */ static const char * const tags[] = /* Value/group tag strings */ { "reserved-00", diff --git a/systemv/cupsctl.c b/systemv/cupsctl.c index e53a71477..e65a4f77b 100644 --- a/systemv/cupsctl.c +++ b/systemv/cupsctl.c @@ -83,12 +83,6 @@ main(int argc, /* I - Number of command-line args */ else if (!strcmp(argv[i], "--no-remote-any")) num_settings = cupsAddOption(CUPS_SERVER_REMOTE_ANY, "0", num_settings, &settings); - else if (!strcmp(argv[i], "--remote-printers")) - num_settings = cupsAddOption(CUPS_SERVER_REMOTE_PRINTERS, "1", - num_settings, &settings); - else if (!strcmp(argv[i], "--no-remote-printers")) - num_settings = cupsAddOption(CUPS_SERVER_REMOTE_PRINTERS, "0", - num_settings, &settings); else if (!strcmp(argv[i], "--share-printers")) num_settings = cupsAddOption(CUPS_SERVER_SHARE_PRINTERS, "1", num_settings, &settings); @@ -219,8 +213,6 @@ usage(const char *opt) /* I - Option character/string */ "administration on/off.")); _cupsLangPuts(stdout, _(" --[no-]remote-any Allow/prevent access " "from the Internet.")); - _cupsLangPuts(stdout, _(" --[no-]remote-printers Show/hide remote " - "printers.")); _cupsLangPuts(stdout, _(" --[no-]share-printers Turn printer sharing " "on/off.")); _cupsLangPuts(stdout, _(" --[no-]user-cancel-any Allow/prevent users to " diff --git a/systemv/lpadmin.c b/systemv/lpadmin.c index 64c3f84e9..5fe0b9bbc 100644 --- a/systemv/lpadmin.c +++ b/systemv/lpadmin.c @@ -1090,8 +1090,7 @@ delete_printer_option(http_t *http, /* I - Server connection */ * option with deleteAttr tag */ - if (get_printer_type(http, printer, uri, sizeof(uri)) & - (CUPS_PRINTER_CLASS | CUPS_PRINTER_IMPLICIT)) + if (get_printer_type(http, printer, uri, sizeof(uri)) & CUPS_PRINTER_CLASS) request = ippNewRequest(CUPS_ADD_MODIFY_CLASS); else request = ippNewRequest(CUPS_ADD_MODIFY_PRINTER); @@ -1145,8 +1144,7 @@ enable_printer(http_t *http, /* I - Server connection */ * printer-is-accepting-jobs */ - if (get_printer_type(http, printer, uri, sizeof(uri)) & - (CUPS_PRINTER_CLASS | CUPS_PRINTER_IMPLICIT)) + if (get_printer_type(http, printer, uri, sizeof(uri)) & CUPS_PRINTER_CLASS) request = ippNewRequest(CUPS_ADD_MODIFY_CLASS); else request = ippNewRequest(CUPS_ADD_MODIFY_PRINTER); @@ -1224,7 +1222,7 @@ get_printer_type(http_t *http, /* I - Server connection */ { type = (cups_ptype_t)attr->values[0].integer; - if (type & (CUPS_PRINTER_CLASS | CUPS_PRINTER_IMPLICIT)) + if (type & CUPS_PRINTER_CLASS) httpAssembleURIf(HTTP_URI_CODING_ALL, uri, urisize, "ipp", NULL, "localhost", ippPort(), "/classes/%s", printer); } @@ -1283,8 +1281,7 @@ set_printer_options( * other options */ - if (get_printer_type(http, printer, uri, sizeof(uri)) & - (CUPS_PRINTER_CLASS | CUPS_PRINTER_IMPLICIT)) + if (get_printer_type(http, printer, uri, sizeof(uri)) & CUPS_PRINTER_CLASS) request = ippNewRequest(CUPS_ADD_MODIFY_CLASS); else request = ippNewRequest(CUPS_ADD_MODIFY_PRINTER); diff --git a/systemv/lpstat.c b/systemv/lpstat.c index eae93bba0..20ef8bf00 100644 --- a/systemv/lpstat.c +++ b/systemv/lpstat.c @@ -580,6 +580,9 @@ match_list(const char *list, /* I - List of names */ if (!list || !*list) return (1); + if (!name) + return (0); + while (*list) { /* diff --git a/templates/admin.tmpl b/templates/admin.tmpl index 477da139e..c76eb9c5e 100644 --- a/templates/admin.tmpl +++ b/templates/admin.tmpl @@ -45,19 +45,9 @@

    Advanced
    - Show printers shared by other systems
    -        Protocols\: - CUPS -{HAVE_LDAP? LDAP:} -{HAVE_LIBSLP? SLP:}
    Share printers connected to this system
            Max clients\:
    -        Protocols\: - CUPS -{HAVE_DNSSD? DNS-SD:} -{HAVE_LDAP? LDAP:} -{HAVE_LIBSLP? SLP:}
             Allow printing from the Internet
             Advertise web interface
    Allow remote administration
    @@ -75,7 +65,6 @@

    Advanced
    - Show printers shared by other systems
    Share printers connected to this system
             Allow printing from the Internet
    Allow remote administration
    diff --git a/test/5.1-lpadmin.sh b/test/5.1-lpadmin.sh index a21980ea6..6dfd6f50e 100644 --- a/test/5.1-lpadmin.sh +++ b/test/5.1-lpadmin.sh @@ -17,7 +17,7 @@ echo "Add Printer Test" echo "" echo " lpadmin -p Test3 -v file:/dev/null -E -m drv:///sample.drv/deskjet.ppd" -../systemv/lpadmin -p Test3 -v file:/dev/null -E -m drv:///sample.drv/deskjet.ppd 2>&1 +$VALGRIND ../systemv/lpadmin -p Test3 -v file:/dev/null -E -m drv:///sample.drv/deskjet.ppd 2>&1 if test $? != 0; then echo " FAILED" exit 1 @@ -29,7 +29,7 @@ echo "" echo "Modify Printer Test" echo "" echo " lpadmin -p Test3 -v file:/tmp/Test3 -o PageSize=A4" -../systemv/lpadmin -p Test3 -v file:/tmp/Test3 -o PageSize=A4 2>&1 +$VALGRIND ../systemv/lpadmin -p Test3 -v file:/tmp/Test3 -o PageSize=A4 2>&1 if test $? != 0; then echo " FAILED" exit 1 @@ -41,7 +41,7 @@ echo "" echo "Delete Printer Test" echo "" echo " lpadmin -x Test3" -../systemv/lpadmin -x Test3 2>&1 +$VALGRIND ../systemv/lpadmin -x Test3 2>&1 if test $? != 0; then echo " FAILED" exit 1 diff --git a/test/5.2-lpc.sh b/test/5.2-lpc.sh index b6908052c..ff15a8715 100644 --- a/test/5.2-lpc.sh +++ b/test/5.2-lpc.sh @@ -17,7 +17,7 @@ echo "LPC Test" echo "" echo " lpc status" -../berkeley/lpc status 2>&1 +$VALGRIND ../berkeley/lpc status 2>&1 if test $? != 0; then echo " FAILED" exit 1 diff --git a/test/5.3-lpq.sh b/test/5.3-lpq.sh index cff0a5597..633508c5a 100644 --- a/test/5.3-lpq.sh +++ b/test/5.3-lpq.sh @@ -17,7 +17,7 @@ echo "LPQ Test" echo "" echo " lpq -P Test1" -../berkeley/lpq -P Test1 2>&1 +$VALGRIND ../berkeley/lpq -P Test1 2>&1 if test $? != 0; then echo " FAILED" exit 1 diff --git a/test/5.4-lpstat.sh b/test/5.4-lpstat.sh index 4b34d11dd..b2e38f12e 100644 --- a/test/5.4-lpstat.sh +++ b/test/5.4-lpstat.sh @@ -4,7 +4,7 @@ # # Test the lpstat command. # -# Copyright 2007-2009 by Apple Inc. +# Copyright 2007-2011 by Apple Inc. # Copyright 1997-2005 by Easy Software Products, all rights reserved. # # These coded instructions, statements, and computer programs are the @@ -17,7 +17,7 @@ echo "LPSTAT Test" echo "" echo " lpstat -t" -../systemv/lpstat -t 2>&1 +$VALGRIND ../systemv/lpstat -t 2>&1 if test $? != 0; then echo " FAILED" exit 1 @@ -29,7 +29,7 @@ echo "" echo "LPSTAT Test" echo "" echo " lpstat -H" -server="`../systemv/lpstat -H 2>&1`" +server="`$VALGRIND ../systemv/lpstat -H 2>&1`" if test $? != 0 -o "x$server" != xlocalhost:8631; then echo " FAILED ($server)" exit 1 diff --git a/test/5.5-lp.sh b/test/5.5-lp.sh index 9dd1dd001..f74e79ba9 100644 --- a/test/5.5-lp.sh +++ b/test/5.5-lp.sh @@ -4,7 +4,7 @@ # # Test the lp command. # -# Copyright 2007-2009 by Apple Inc. +# Copyright 2007-2011 by Apple Inc. # Copyright 1997-2005 by Easy Software Products, all rights reserved. # # These coded instructions, statements, and computer programs are the @@ -17,7 +17,7 @@ echo "LP Default Test" echo "" echo " lp testfile.pdf" -../systemv/lp testfile.pdf 2>&1 +$VALGRIND ../systemv/lp testfile.pdf 2>&1 if test $? != 0; then echo " FAILED" exit 1 @@ -29,7 +29,7 @@ echo "" echo "LP Destination Test" echo "" echo " lp -d Test2 testfile.jpg" -../systemv/lp -d Test2 testfile.jpg 2>&1 +$VALGRIND ../systemv/lp -d Test2 testfile.jpg 2>&1 if test $? != 0; then echo " FAILED" exit 1 @@ -41,7 +41,7 @@ echo "" echo "LP Options Test" echo "" echo " lp -d Test1 -P 1-4 -o job-sheets=classified,classified testfile.pdf" -../systemv/lp -d Test1 -P 1-4 -o job-sheets=classified,classified testfile.pdf 2>&1 +$VALGRIND ../systemv/lp -d Test1 -P 1-4 -o job-sheets=classified,classified testfile.pdf 2>&1 if test $? != 0; then echo " FAILED" exit 1 @@ -56,16 +56,14 @@ echo " lp -d Test1 testfile.jpg" echo " lp -d Test2 testfile.jpg" i=0 while test $i -lt $1; do - echo " flood copy $i..." 1>&2 - j=1 while test $j -le $2; do - ../systemv/lp -d test-$j testfile.jpg 2>&1 + $VALGRIND ../systemv/lp -d test-$j testfile.jpg 2>&1 j=`expr $j + 1` done - ../systemv/lp -d Test1 testfile.jpg 2>&1 & - ../systemv/lp -d Test2 testfile.jpg 2>&1 & + $VALGRIND ../systemv/lp -d Test1 testfile.jpg 2>&1 & + $VALGRIND ../systemv/lp -d Test2 testfile.jpg 2>&1 & lppid=$! i=`expr $i + 1` diff --git a/test/5.6-lpr.sh b/test/5.6-lpr.sh index 72c757106..17646aa88 100644 --- a/test/5.6-lpr.sh +++ b/test/5.6-lpr.sh @@ -4,7 +4,7 @@ # # Test the lpr command. # -# Copyright 2007-2009 by Apple Inc. +# Copyright 2007-2011 by Apple Inc. # Copyright 1997-2005 by Easy Software Products, all rights reserved. # # These coded instructions, statements, and computer programs are the @@ -17,7 +17,7 @@ echo "LPR Default Test" echo "" echo " lpr testfile.pdf" -../berkeley/lpr testfile.pdf 2>&1 +$VALGRIND ../berkeley/lpr testfile.pdf 2>&1 if test $? != 0; then echo " FAILED" exit 1 @@ -29,7 +29,7 @@ echo "" echo "LPR Destination Test" echo "" echo " lpr -P Test2 testfile.jpg" -../berkeley/lpr -P Test2 testfile.jpg 2>&1 +$VALGRIND ../berkeley/lpr -P Test2 testfile.jpg 2>&1 if test $? != 0; then echo " FAILED" exit 1 @@ -41,7 +41,7 @@ echo "" echo "LPR Options Test" echo "" echo " lpr -P Test1 -o number-up=4 -o job-sheets=standard,none testfile.pdf" -../berkeley/lpr -P Test1 -o number-up=4 -o job-sheets=standard,none testfile.pdf 2>&1 +$VALGRIND ../berkeley/lpr -P Test1 -o number-up=4 -o job-sheets=standard,none testfile.pdf 2>&1 if test $? != 0; then echo " FAILED" exit 1 @@ -56,16 +56,14 @@ echo " lpr -P Test1 testfile.jpg" echo " lpr -P Test2 testfile.jpg" i=0 while test $i -lt $1; do - echo " flood copy $i..." 1>&2 - j=1 while test $j -le $2; do - ../berkeley/lpr -P test-$j testfile.jpg 2>&1 + $VALGRIND ../berkeley/lpr -P test-$j testfile.jpg 2>&1 j=`expr $j + 1` done - ../berkeley/lpr -P Test1 testfile.jpg 2>&1 & - ../berkeley/lpr -P Test2 testfile.jpg 2>&1 & + $VALGRIND ../berkeley/lpr -P Test1 testfile.jpg 2>&1 & + $VALGRIND ../berkeley/lpr -P Test2 testfile.jpg 2>&1 & lprpid=$! i=`expr $i + 1` diff --git a/test/5.7-lprm.sh b/test/5.7-lprm.sh index bcb721169..4b96920bb 100644 --- a/test/5.7-lprm.sh +++ b/test/5.7-lprm.sh @@ -4,7 +4,7 @@ # # Test the lprm command. # -# Copyright 2007 by Apple Inc. +# Copyright 2007-2011 by Apple Inc. # Copyright 1997-2005 by Easy Software Products, all rights reserved. # # These coded instructions, statements, and computer programs are the @@ -17,9 +17,9 @@ echo "LPRM Current Test" echo "" echo " lpr -o job-hold-until=indefinite testfile.jpg" -../berkeley/lpr -o job-hold-until=indefinite testfile.jpg 2>&1 +$VALGRIND ../berkeley/lpr -o job-hold-until=indefinite testfile.jpg 2>&1 echo " lprm" -../berkeley/lprm 2>&1 +$VALGRIND ../berkeley/lprm 2>&1 if test $? != 0; then echo " FAILED" exit 1 @@ -31,9 +31,9 @@ echo "" echo "LPRM Destination Test" echo "" echo " lpr -P Test1 -o job-hold-until=indefinite testfile.jpg" -../berkeley/lpr -P Test1 -o job-hold-until=indefinite testfile.jpg 2>&1 +$VALGRIND ../berkeley/lpr -P Test1 -o job-hold-until=indefinite testfile.jpg 2>&1 echo " lprm Test1" -../berkeley/lprm Test1 2>&1 +$VALGRIND ../berkeley/lprm Test1 2>&1 if test $? != 0; then echo " FAILED" exit 1 diff --git a/test/5.8-cancel.sh b/test/5.8-cancel.sh index 7cf31b0da..88b7dd4e2 100644 --- a/test/5.8-cancel.sh +++ b/test/5.8-cancel.sh @@ -4,7 +4,7 @@ # # Test the cancel command. # -# Copyright 2007-2008 by Apple Inc. +# Copyright 2007-2011 by Apple Inc. # Copyright 1997-2006 by Easy Software Products, all rights reserved. # # These coded instructions, statements, and computer programs are the @@ -17,9 +17,9 @@ echo "Cancel Destination Test" echo "" echo " lp -d Test1 -o job-hold-until=indefinite testfile.jpg" -../systemv/lp -d Test1 -o job-hold-until=indefinite testfile.jpg 2>&1 +$VALGRIND ../systemv/lp -d Test1 -o job-hold-until=indefinite testfile.jpg 2>&1 echo " cancel Test1" -../systemv/cancel Test1 2>&1 +$VALGRIND ../systemv/cancel Test1 2>&1 if test $? != 0; then echo " FAILED" exit 1 @@ -31,7 +31,7 @@ echo "" echo "Cancel All Test" echo "" echo " cancel -a" -../systemv/cancel -a 2>&1 +$VALGRIND ../systemv/cancel -a 2>&1 if test $? != 0; then echo " FAILED" exit 1 diff --git a/test/5.9-lpinfo.sh b/test/5.9-lpinfo.sh index 1902aeb99..a6ea3645e 100644 --- a/test/5.9-lpinfo.sh +++ b/test/5.9-lpinfo.sh @@ -4,7 +4,7 @@ # # Test the lpinfo command. # -# Copyright 2007-2008 by Apple Inc. +# Copyright 2007-2011 by Apple Inc. # Copyright 1997-2005 by Easy Software Products, all rights reserved. # # These coded instructions, statements, and computer programs are the @@ -17,7 +17,7 @@ echo "LPINFO Devices Test" echo "" echo " lpinfo -v" -../systemv/lpinfo -v 2>&1 +$VALGRIND ../systemv/lpinfo -v 2>&1 if test $? != 0; then echo " FAILED" exit 1 @@ -29,7 +29,7 @@ echo "" echo "LPINFO Drivers Test" echo "" echo " lpinfo -m" -../systemv/lpinfo -m 2>&1 +$VALGRIND ../systemv/lpinfo -m 2>&1 if test $? != 0; then echo " FAILED" exit 1 @@ -41,7 +41,7 @@ echo "" echo "LPINFO Drivers Test" echo "" echo " lpinfo -m | grep -q sample.drv" -../systemv/lpinfo -m | grep -q sample.drv 2>&1 +$VALGRIND ../systemv/lpinfo -m | grep -q sample.drv 2>&1 if test $? != 0; then echo " FAILED" exit 1 diff --git a/test/ipp-1.1.test b/test/ipp-1.1.test index 8e789dcb6..749e16287 100644 --- a/test/ipp-1.1.test +++ b/test/ipp-1.1.test @@ -656,6 +656,8 @@ DEFINE IPP_URI_SCHEME "/^ipps?://.+$$/" # Wait for job to complete... { + SKIP-IF-NOT-DEFINED job-id + NAME "Get-Job-Attributes Until Job Complete" OPERATION Get-Job-Attributes GROUP operation-attributes-tag diff --git a/test/ippserver.c b/test/ippserver.c index 23b4ed970..ec05bda54 100644 --- a/test/ippserver.c +++ b/test/ippserver.c @@ -18,7 +18,6 @@ * main() - Main entry to the sample server. * clean_jobs() - Clean out old (completed) jobs. * compare_jobs() - Compare two jobs. - * copy_attribute() - Copy a single attribute. * copy_attributes() - Copy attributes from one request to * another. * copy_job_attrs() - Copy job attributes to the response. @@ -254,8 +253,6 @@ typedef struct _ipp_client_s /**** Client data ****/ static void clean_jobs(_ipp_printer_t *printer); static int compare_jobs(_ipp_job_t *a, _ipp_job_t *b); -static ipp_attribute_t *copy_attribute(ipp_t *to, ipp_attribute_t *attr, - ipp_tag_t group_tag, int quickcopy); static void copy_attributes(ipp_t *to, ipp_t *from, cups_array_t *ra, ipp_tag_t group_tag, int quickcopy); static void copy_job_attributes(_ipp_client_t *client, @@ -576,191 +573,6 @@ compare_jobs(_ipp_job_t *a, /* I - First job */ } -/* - * 'copy_attribute()' - Copy a single attribute. - */ - -static ipp_attribute_t * /* O - New attribute */ -copy_attribute( - ipp_t *to, /* O - Destination request/response */ - ipp_attribute_t *attr, /* I - Attribute to copy */ - ipp_tag_t group_tag, /* I - Group to put the copy in */ - int quickcopy) /* I - Do a quick copy? */ -{ - int i; /* Looping var */ - ipp_attribute_t *toattr; /* Destination attribute */ - - - if (Verbosity && attr->name) - { - char buffer[2048]; /* Attribute value */ - - _ippAttrString(attr, buffer, sizeof(buffer)); - - fprintf(stderr, "Copying %s (%s%s) %s\n", attr->name, - attr->num_values > 1 ? "1setOf " : "", - ippTagString(attr->value_tag & ~IPP_TAG_COPY), buffer); - } - - switch (attr->value_tag & ~IPP_TAG_COPY) - { - case IPP_TAG_ZERO : - toattr = ippAddSeparator(to); - break; - - case IPP_TAG_INTEGER : - case IPP_TAG_ENUM : - toattr = ippAddIntegers(to, group_tag, attr->value_tag, - attr->name, attr->num_values, NULL); - - for (i = 0; i < attr->num_values; i ++) - toattr->values[i].integer = attr->values[i].integer; - break; - - case IPP_TAG_BOOLEAN : - toattr = ippAddBooleans(to, group_tag, attr->name, - attr->num_values, NULL); - - for (i = 0; i < attr->num_values; i ++) - toattr->values[i].boolean = attr->values[i].boolean; - break; - - case IPP_TAG_TEXT : - case IPP_TAG_NAME : - case IPP_TAG_KEYWORD : - case IPP_TAG_URI : - case IPP_TAG_URISCHEME : - case IPP_TAG_CHARSET : - case IPP_TAG_LANGUAGE : - case IPP_TAG_MIMETYPE : - toattr = ippAddStrings(to, group_tag, - (ipp_tag_t)(attr->value_tag | quickcopy), - attr->name, attr->num_values, NULL, NULL); - - if (quickcopy) - { - for (i = 0; i < attr->num_values; i ++) - toattr->values[i].string.text = attr->values[i].string.text; - } - else - { - for (i = 0; i < attr->num_values; i ++) - toattr->values[i].string.text = - _cupsStrAlloc(attr->values[i].string.text); - } - break; - - case IPP_TAG_DATE : - toattr = ippAddDate(to, group_tag, attr->name, - attr->values[0].date); - break; - - case IPP_TAG_RESOLUTION : - toattr = ippAddResolutions(to, group_tag, attr->name, - attr->num_values, IPP_RES_PER_INCH, - NULL, NULL); - - for (i = 0; i < attr->num_values; i ++) - { - toattr->values[i].resolution.xres = attr->values[i].resolution.xres; - toattr->values[i].resolution.yres = attr->values[i].resolution.yres; - toattr->values[i].resolution.units = attr->values[i].resolution.units; - } - break; - - case IPP_TAG_RANGE : - toattr = ippAddRanges(to, group_tag, attr->name, - attr->num_values, NULL, NULL); - - for (i = 0; i < attr->num_values; i ++) - { - toattr->values[i].range.lower = attr->values[i].range.lower; - toattr->values[i].range.upper = attr->values[i].range.upper; - } - break; - - case IPP_TAG_TEXTLANG : - case IPP_TAG_NAMELANG : - toattr = ippAddStrings(to, group_tag, - (ipp_tag_t)(attr->value_tag | quickcopy), - attr->name, attr->num_values, NULL, NULL); - - if (quickcopy) - { - for (i = 0; i < attr->num_values; i ++) - { - toattr->values[i].string.charset = attr->values[i].string.charset; - toattr->values[i].string.text = attr->values[i].string.text; - } - } - else - { - for (i = 0; i < attr->num_values; i ++) - { - if (!i) - toattr->values[i].string.charset = - _cupsStrAlloc(attr->values[i].string.charset); - else - toattr->values[i].string.charset = - toattr->values[0].string.charset; - - toattr->values[i].string.text = - _cupsStrAlloc(attr->values[i].string.text); - } - } - break; - - case IPP_TAG_BEGIN_COLLECTION : - toattr = ippAddCollections(to, group_tag, attr->name, - attr->num_values, NULL); - - for (i = 0; i < attr->num_values; i ++) - { - toattr->values[i].collection = attr->values[i].collection; - attr->values[i].collection->use ++; - } - break; - - case IPP_TAG_STRING : - if (quickcopy) - { - toattr = ippAddOctetString(to, group_tag, attr->name, NULL, 0); - toattr->value_tag |= quickcopy; - toattr->values[0].unknown.data = attr->values[0].unknown.data; - toattr->values[0].unknown.length = attr->values[0].unknown.length; - } - else - toattr = ippAddOctetString(to, attr->group_tag, attr->name, - attr->values[0].unknown.data, - attr->values[0].unknown.length); - break; - - default : - toattr = ippAddIntegers(to, group_tag, attr->value_tag, - attr->name, attr->num_values, NULL); - - for (i = 0; i < attr->num_values; i ++) - { - toattr->values[i].unknown.length = attr->values[i].unknown.length; - - if (toattr->values[i].unknown.length > 0) - { - if ((toattr->values[i].unknown.data = - malloc(toattr->values[i].unknown.length)) == NULL) - toattr->values[i].unknown.length = 0; - else - memcpy(toattr->values[i].unknown.data, - attr->values[i].unknown.data, - toattr->values[i].unknown.length); - } - } - break; /* anti-compiler-warning-code */ - } - - return (toattr); -} - - /* * 'copy_attributes()' - Copy attributes from one request to another. */ @@ -789,7 +601,7 @@ copy_attributes(ipp_t *to, /* I - Destination request */ continue; if (!ra || cupsArrayFind(ra, fromattr->name)) - copy_attribute(to, fromattr, fromattr->group_tag, quickcopy); + ippCopyAttribute(to, fromattr, quickcopy); } } @@ -1215,7 +1027,7 @@ create_printer(const char *servername, /* I - Server hostname (NULL for default) /* media-size-supported value */ ipp_t *media_col_default; /* media-col-default value */ - ipp_value_t *media_col_value; + _ipp_value_t *media_col_value; /* Current media-col-database value */ int k_supported; /* Maximum file size supported */ #ifdef HAVE_STATVFS @@ -2084,7 +1896,7 @@ debug_attributes(const char *title, /* I - Title */ if (attr->name) { - _ippAttrString(attr, buffer, sizeof(buffer)); + ippAttributeString(attr, buffer, sizeof(buffer)); fprintf(stderr, " %s (%s%s) %s\n", attr->name, attr->num_values > 1 ? "1setOf " : "", ippTagString(attr->value_tag), buffer); @@ -4978,12 +4790,16 @@ respond_unsupported( _ipp_client_t *client, /* I - Client */ ipp_attribute_t *attr) /* I - Atribute */ { + ipp_attribute_t *temp; /* Copy of attribute */ + + if (!client->response->attrs) respond_ipp(client, IPP_ATTRIBUTES, "Unsupported %s %s%s value.", attr->name, attr->num_values > 1 ? "1setOf " : "", ippTagString(attr->value_tag)); - copy_attribute(client->response, attr, IPP_TAG_UNSUPPORTED_GROUP, 0); + temp = ippCopyAttribute(client->response, attr, 0); + ippSetGroupTag(client->response, &temp, IPP_TAG_UNSUPPORTED_GROUP); } diff --git a/test/ipptool.c b/test/ipptool.c index 59b83253d..c9060905d 100644 --- a/test/ipptool.c +++ b/test/ipptool.c @@ -1146,7 +1146,7 @@ do_tests(_cups_vars_t *vars, /* I - Variables */ if ((tempcol = realloc(lastcol, sizeof(ipp_attribute_t) + (lastcol->num_values + 1) * - sizeof(ipp_value_t))) == NULL) + sizeof(_ipp_value_t))) == NULL) { print_fatal_error("Unable to allocate memory on line %d.", linenum); pass = 0; @@ -1499,21 +1499,22 @@ do_tests(_cups_vars_t *vars, /* I - Variables */ } expand_variables(vars, token, temp, sizeof(token)); + attrptr = NULL; switch (value) { case IPP_TAG_BOOLEAN : if (!_cups_strcasecmp(token, "true")) - ippAddBoolean(request, group, attr, 1); + attrptr = ippAddBoolean(request, group, attr, 1); else - ippAddBoolean(request, group, attr, atoi(token)); + attrptr = ippAddBoolean(request, group, attr, atoi(token)); break; case IPP_TAG_INTEGER : case IPP_TAG_ENUM : if (!strchr(token, ',')) - ippAddInteger(request, group, value, attr, - strtol(token, &tokenptr, 0)); + attrptr = ippAddInteger(request, group, value, attr, + strtol(token, &tokenptr, 0)); else { int values[100], /* Values */ @@ -1532,7 +1533,7 @@ do_tests(_cups_vars_t *vars, /* I - Variables */ num_values ++; } - ippAddIntegers(request, group, value, attr, num_values, values); + attrptr = ippAddIntegers(request, group, value, attr, num_values, values); } if (!tokenptr || *tokenptr) @@ -1568,14 +1569,14 @@ do_tests(_cups_vars_t *vars, /* I - Variables */ } if (!_cups_strcasecmp(ptr, "dpi")) - ippAddResolution(request, group, attr, IPP_RES_PER_INCH, - xres, yres); + attrptr = ippAddResolution(request, group, attr, IPP_RES_PER_INCH, + xres, yres); else if (!_cups_strcasecmp(ptr, "dpc")) - ippAddResolution(request, group, attr, IPP_RES_PER_CM, - xres, yres); + attrptr = ippAddResolution(request, group, attr, IPP_RES_PER_CM, + xres, yres); else - ippAddResolution(request, group, attr, (ipp_res_t)0, - xres, yres); + attrptr = ippAddResolution(request, group, attr, (ipp_res_t)0, + xres, yres); } break; @@ -1600,8 +1601,8 @@ do_tests(_cups_vars_t *vars, /* I - Variables */ goto test_exit; } - ippAddRanges(request, group, attr, num_vals / 2, lowers, - uppers); + attrptr = ippAddRanges(request, group, attr, num_vals / 2, lowers, + uppers); } break; @@ -1613,7 +1614,7 @@ do_tests(_cups_vars_t *vars, /* I - Variables */ if (col) { - lastcol = ippAddCollection(request, group, attr, col); + attrptr = lastcol = ippAddCollection(request, group, attr, col); ippDelete(col); } else @@ -1648,7 +1649,7 @@ do_tests(_cups_vars_t *vars, /* I - Variables */ case IPP_TAG_LANGUAGE : case IPP_TAG_MIMETYPE : if (!strchr(token, ',')) - ippAddString(request, group, value, attr, NULL, token); + attrptr = ippAddString(request, group, value, attr, NULL, token); else { /* @@ -1670,11 +1671,19 @@ do_tests(_cups_vars_t *vars, /* I - Variables */ num_values ++; } - ippAddStrings(request, group, value, attr, num_values, - NULL, (const char **)values); + attrptr = ippAddStrings(request, group, value, attr, num_values, + NULL, (const char **)values); } break; } + + if (!attrptr) + { + print_fatal_error("Unable to add attribute on line %d: %s", linenum, + cupsLastErrorString()); + pass = 0; + goto test_exit; + } } else if (!_cups_strcasecmp(token, "FILE")) { @@ -2327,6 +2336,9 @@ do_tests(_cups_vars_t *vars, /* I - Variables */ switch (attrptr->group_tag) { + case IPP_TAG_ZERO : + break; + case IPP_TAG_OPERATION : prev_pass = pass = 0; break; @@ -2358,7 +2370,8 @@ do_tests(_cups_vars_t *vars, /* I - Variables */ if (!pass) break; - group = attrptr->group_tag; + if (attrptr->group_tag != IPP_TAG_ZERO) + group = attrptr->group_tag; } if (!validate_attr(attrptr, 0)) @@ -2434,7 +2447,7 @@ do_tests(_cups_vars_t *vars, /* I - Variables */ } if (found) - _ippAttrString(found, buffer, sizeof(buffer)); + ippAttributeString(found, buffer, sizeof(buffer)); if (found && !with_value(expect->with_value, expect->with_regex, found, 0, @@ -2535,18 +2548,19 @@ do_tests(_cups_vars_t *vars, /* I - Variables */ { puts(prev_pass ? "PASS]" : "FAIL]"); - if (Verbosity && response) + if (!prev_pass || (Verbosity && response)) { printf(" RECEIVED: %lu bytes in response\n", (unsigned long)ippLength(response)); - printf(" status-code = %x (%s)\n", cupsLastError(), - ippErrorString(cupsLastError())); + printf(" status-code = %s (%s)\n", ippErrorString(cupsLastError()), + cupsLastErrorString()); - for (attrptr = response->attrs; - attrptr != NULL; - attrptr = attrptr->next) - { - print_attr(attrptr, NULL); + if (response) + { + for (attrptr = response->attrs; + attrptr != NULL; + attrptr = attrptr->next) + print_attr(attrptr, NULL); } } } @@ -2567,7 +2581,7 @@ do_tests(_cups_vars_t *vars, /* I - Variables */ attrptr = ippFindNextAttribute(response, displayed[i], IPP_TAG_ZERO)) { - width = _ippAttrString(attrptr, NULL, 0); + width = ippAttributeString(attrptr, NULL, 0); if (width > widths[i]) widths[i] = width; } @@ -2732,6 +2746,9 @@ do_tests(_cups_vars_t *vars, /* I - Variables */ switch (attrptr->group_tag) { + case IPP_TAG_ZERO : + break; + case IPP_TAG_OPERATION : prev_pass = pass = 0; break; @@ -2768,7 +2785,8 @@ do_tests(_cups_vars_t *vars, /* I - Variables */ break; } - group = attrptr->group_tag; + if (attrptr->group_tag != IPP_TAG_ZERO) + group = attrptr->group_tag; } validate_attr(attrptr, 1); @@ -3216,7 +3234,7 @@ get_collection(_cups_vars_t *vars, /* I - Variables */ if ((tempcol = realloc(lastcol, sizeof(ipp_attribute_t) + (lastcol->num_values + 1) * - sizeof(ipp_value_t))) == NULL) + sizeof(_ipp_value_t))) == NULL) { print_fatal_error("Unable to allocate memory on line %d.", *linenum); goto col_error; @@ -3737,14 +3755,14 @@ print_attr(ipp_attribute_t *attr, /* I - Attribute to print */ if (Output == _CUPS_OUTPUT_PLIST) { fputs("language", stdout); - print_xml_string(NULL, attr->values[i].string.charset); + print_xml_string(NULL, attr->values[i].string.language); fputs("string", stdout); print_xml_string(NULL, attr->values[i].string.text); puts(""); } else - printf("\"%s\"(%s) ", attr->values[i].string.text, - attr->values[i].string.charset); + printf("\"%s\"[%s] ", attr->values[i].string.text, + attr->values[i].string.language); break; case IPP_TAG_BEGIN_COLLECTION : @@ -3798,7 +3816,7 @@ print_attr(ipp_attribute_t *attr, /* I - Attribute to print */ ippTagString(attr->value_tag)); } - _ippAttrString(attr, buffer, sizeof(buffer)); + ippAttributeString(attr, buffer, sizeof(buffer)); puts(buffer); } } @@ -3870,8 +3888,8 @@ print_col(ipp_t *col) /* I - Collection attribute to print */ case IPP_TAG_TEXTLANG : case IPP_TAG_NAMELANG : for (i = 0; i < attr->num_values; i ++) - printf("\"%s\",%s ", attr->values[i].string.text, - attr->values[i].string.charset); + printf("\"%s\"[%s] ", attr->values[i].string.text, + attr->values[i].string.language); break; case IPP_TAG_BEGIN_COLLECTION : @@ -3941,7 +3959,7 @@ print_csv( break; else if (!strcmp(current->name, displayed[i])) { - _ippAttrString(current, buffer, maxlength); + ippAttributeString(current, buffer, maxlength); break; } } @@ -4062,7 +4080,7 @@ print_line( break; else if (!strcmp(current->name, displayed[i])) { - _ippAttrString(current, buffer, maxlength); + ippAttributeString(current, buffer, maxlength); break; } } @@ -5264,7 +5282,7 @@ with_value(char *value, /* I - Value string */ } break; case '>' : - if (attr->values[i].range.lower > intvalue) + if (attr->values[i].range.upper > intvalue) { snprintf(matchbuf, matchlen, "%d-%d", attr->values[i].range.lower, diff --git a/test/run-stp-tests.sh b/test/run-stp-tests.sh index 255f3066d..147650d39 100755 --- a/test/run-stp-tests.sh +++ b/test/run-stp-tests.sh @@ -203,12 +203,17 @@ echo "" case "$usevalgrind" in Y* | y*) - valgrind="valgrind --tool=memcheck --log-file=/tmp/cups-$user/log/valgrind.%p --error-limit=no --leak-check=yes --trace-children=yes --read-var-info=yes" + VALGRIND="valgrind --tool=memcheck --log-file=/tmp/cups-$user/log/valgrind.%p --error-limit=no --leak-check=yes --trace-children=yes --read-var-info=yes" + if test `uname` = Darwin; then + VALGRIND="$VALGRIND --dsymutil=yes" + fi + export VALGRIND echo "Using Valgrind; log files can be found in /tmp/cups-$user/log..." ;; *) - valgrind="" + VALGRIND="" + export VALGRIND ;; esac @@ -235,14 +240,14 @@ case "$usedebugprintfs" in echo "Enabling debug printfs; log files can be found in /tmp/cups-$user/log..." CUPS_DEBUG_LOG="/tmp/cups-$user/log/debug_printfs.%d"; export CUPS_DEBUG_LOG CUPS_DEBUG_LEVEL=5; export CUPS_DEBUG_LEVEL - CUPS_DEBUG_FILTER='^(http|_http|ipp|_ipp|cups.*Request|cupsGetRespond|cupsSend).*$'; export CUPS_DEBUG_FILTER + CUPS_DEBUG_FILTER='^(http|_http|ipp|_ipp|cups.*Request|cupsGetResponse|cupsSend).*$'; export CUPS_DEBUG_FILTER ;; 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9) echo "Enabling debug printfs; log files can be found in /tmp/cups-$user/log..." CUPS_DEBUG_LOG="/tmp/cups-$user/log/debug_printfs.%d"; export CUPS_DEBUG_LOG CUPS_DEBUG_LEVEL=$usedebugprintf; export CUPS_DEBUG_LEVEL - CUPS_DEBUG_FILTER='^(http|_http|ipp|_ipp|cups.*Request|cupsGetRespond|cupsSend).*$'; export CUPS_DEBUG_FILTER + CUPS_DEBUG_FILTER='^(http|_http|ipp|_ipp|cups.*Request|cupsGetResponse|cupsSend).*$'; export CUPS_DEBUG_FILTER ;; *) @@ -510,14 +515,14 @@ export LC_MESSAGES # echo "Starting scheduler:" -echo " $valgrind ../scheduler/cupsd -c /tmp/cups-$user/cupsd.conf -f >/tmp/cups-$user/log/debug_log 2>&1 &" +echo " $VALGRIND ../scheduler/cupsd -c /tmp/cups-$user/cupsd.conf -f >/tmp/cups-$user/log/debug_log 2>&1 &" echo "" -if test `uname` = Darwin -a "x$valgrind" = x; then +if test `uname` = Darwin -a "x$VALGRIND" = x; then DYLD_INSERT_LIBRARIES=/usr/lib/libgmalloc.dylib ../scheduler/cupsd -c /tmp/cups-$user/cupsd.conf -f >/tmp/cups-$user/log/debug_log 2>&1 & else - $valgrind ../scheduler/cupsd -c /tmp/cups-$user/cupsd.conf -f >/tmp/cups-$user/log/debug_log 2>&1 & + $VALGRIND ../scheduler/cupsd -c /tmp/cups-$user/cupsd.conf -f >/tmp/cups-$user/log/debug_log 2>&1 & fi cupsd=$! @@ -601,15 +606,17 @@ echo "

    " >>$strfile
     
     fail=0
     for file in 4*.test; do
    -	echo "Performing $file..."
    +	echo $ac_n "Performing $file: $ac_c"
     	echo "" >>$strfile
     
    -	./ipptool -t ipp://localhost:$port/printers $file | tee -a $strfile
    +	$VALGRIND ./ipptool -tI ipp://localhost:$port/printers $file >> $strfile
     	status=$?
     
     	if test $status != 0; then
    -		echo Test failed.
    +		echo FAIL
     		fail=`expr $fail + 1`
    +	else
    +		echo PASS
     	fi
     done
     
    @@ -629,16 +636,18 @@ echo $date by $user on `hostname`. >>$strfile
     echo "
    " >>$strfile
     
     for file in 5*.sh; do
    -	echo "Performing $file..."
    +	echo $ac_n "Performing $file: $ac_c"
     	echo "" >>$strfile
     	echo "\"$file\":" >>$strfile
     
    -	sh $file $pjobs $pprinters | tee -a $strfile
    +	sh $file $pjobs $pprinters >> $strfile
     	status=$?
     
     	if test $status != 0; then
    -		echo Test failed.
    +		echo FAIL
     		fail=`expr $fail + 1`
    +	else
    +		echo PASS
     	fi
     done
     
    diff --git a/vcnet/cups.sln b/vcnet/cups.sln
    index 9dabb8926..45d459319 100644
    --- a/vcnet/cups.sln
    +++ b/vcnet/cups.sln
    @@ -28,6 +28,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ipptool", "ipptool.vcproj",
     		{CB4AA6F2-3E84-45BE-B505-95CD375E8BE3} = {CB4AA6F2-3E84-45BE-B505-95CD375E8BE3}
     	EndProjectSection
     EndProject
    +Project("{54435603-DBB4-11D2-8724-00A0C9A8B90C}") = "ipptool-installer", "ipptool-installer.vdproj", "{6AEA263B-92C0-426F-B5FF-F7F5917B704A}"
    +EndProject
     Global
     	GlobalSection(SolutionConfigurationPlatforms) = preSolution
     		Debug|Win32 = Debug|Win32
    @@ -84,6 +86,14 @@ Global
     		{B246D91E-61F2-4433-BFD2-6C2A96FBD4D4}.Release|Win32.Build.0 = Release|Win32
     		{B246D91E-61F2-4433-BFD2-6C2A96FBD4D4}.Release|x64.ActiveCfg = Release|x64
     		{B246D91E-61F2-4433-BFD2-6C2A96FBD4D4}.Release|x64.Build.0 = Release|x64
    +		{6AEA263B-92C0-426F-B5FF-F7F5917B704A}.Debug|Win32.ActiveCfg = Debug
    +		{6AEA263B-92C0-426F-B5FF-F7F5917B704A}.Debug|Win32.Build.0 = Debug
    +		{6AEA263B-92C0-426F-B5FF-F7F5917B704A}.Debug|x64.ActiveCfg = Debug
    +		{6AEA263B-92C0-426F-B5FF-F7F5917B704A}.Debug|x64.Build.0 = Debug
    +		{6AEA263B-92C0-426F-B5FF-F7F5917B704A}.Release|Win32.ActiveCfg = Release
    +		{6AEA263B-92C0-426F-B5FF-F7F5917B704A}.Release|Win32.Build.0 = Release
    +		{6AEA263B-92C0-426F-B5FF-F7F5917B704A}.Release|x64.ActiveCfg = Release
    +		{6AEA263B-92C0-426F-B5FF-F7F5917B704A}.Release|x64.Build.0 = Release
     	EndGlobalSection
     	GlobalSection(SolutionProperties) = preSolution
     		HideSolutionNode = FALSE
    diff --git a/vcnet/cupstestppd.vcproj b/vcnet/cupstestppd.vcproj
    index 8c3416963..4739f3719 100644
    --- a/vcnet/cupstestppd.vcproj
    +++ b/vcnet/cupstestppd.vcproj
    @@ -21,8 +21,8 @@
     	
     		
    @@ -95,12 +95,11 @@
     			/>
     		
     		
     			
     			
     			
     			
     			
     		
     		
     			
     			
     			
     			
     			
     		
     		
    @@ -95,12 +95,11 @@
     			/>