diff --git a/doc/help/ref-cupsd-conf.html.in b/doc/help/ref-cupsd-conf.html.in
index a35ca4af6..d3610cb84 100644
--- a/doc/help/ref-cupsd-conf.html.in
+++ b/doc/help/ref-cupsd-conf.html.in
@@ -1479,6 +1479,48 @@ the file is assumed to be relative to the
@@ -2985,6 +3027,49 @@ on for secure connections. Multiple
diff --git a/doc/help/spec-ppd.html b/doc/help/spec-ppd.html
index 3c81a763c..1343d71f2 100644
--- a/doc/help/spec-ppd.html
+++ b/doc/help/spec-ppd.html
@@ -2,15 +2,347 @@
-
+
Developing PostScript Printer Drivers
This document describes how to develop printer drivers for PostScript printers. Topics include: printer driver basics, creating new PPD files, importing existing PPD files, using custom filters, implementing color management, and adding Mac OS X features.
diff --git a/filter/ppd-compiler.header b/filter/ppd-compiler.header
index 6afe1b4f0..4af7865f8 100644
--- a/filter/ppd-compiler.header
+++ b/filter/ppd-compiler.header
@@ -1,3 +1,18 @@
+
+
Introduction to the PPD Compiler
This document describes how to use the CUPS PostScript Printer Description
diff --git a/filter/raster-driver.header b/filter/raster-driver.header
index 5ba1fb614..31fc60722 100644
--- a/filter/raster-driver.header
+++ b/filter/raster-driver.header
@@ -1,3 +1,18 @@
+
+
Developing Raster Printer Drivers
This document describes how to develop printer drivers for raster printers. Topics include: printer driver basics, creating new PPD files, using filters, implementing color management, and adding Mac OS X features.
diff --git a/filter/spec-ppd.header b/filter/spec-ppd.header
new file mode 100644
index 000000000..8292be8a7
--- /dev/null
+++ b/filter/spec-ppd.header
@@ -0,0 +1,32 @@
+
+
+
CUPS PPD Extensions
+
+
This specification describes the attributes and extensions that CUPS adds to Adobe TechNote #5003: PostScript Printer Description File Format Specification Version 4.3. PostScript Printer Description ("PPD") files describe the capabilities of each printer and are used by CUPS to support printer-specific features and intelligent filtering.
+
+
diff --git a/filter/spec-ppd.shtml b/filter/spec-ppd.shtml
new file mode 100644
index 000000000..96fb88133
--- /dev/null
+++ b/filter/spec-ppd.shtml
@@ -0,0 +1,1851 @@
+
+
+
The PPD format is text-based and uses lines of up to 255 characters terminated by a carriage return, linefeed, or combination of carriage return and line feed. The following ABNF definition [RFC5234] defines the general format of lines in a PPD file:
+
+
+PPD-FILE = HEADER +(DATA / COMMENT / LINE-END)
+
+HEADER = "*PPD-Adobe:" *WSP DQUOTE VERSION DQUOTE LINE-END
+
+VERSION = "4.0" / "4.1" / "4.2" / "4.3"
+
+COMMENT = "*%" *TCHAR LINE-END
+
+DATA = "*" 1*KCHAR [ WSP 1*KCHAR [ "/" 1*TCHAR ] ] ":"
+ 1*(*WSP VALUE) LINE-END
+
+VALUE = 1*TCHAR / DQUOTE 1*SCHAR DQUOTE
+
+KCHAR = ALPHA / DIGIT / "_" / "." / "-"
+
+SCHAR = LINE-END / WSP / %x21.23-7E.A0-FF
+
+TCHAR = %x20-7E.A0-FF
+
+LINE-END = CR / LF / CR LF
+
+
+
+
+
+
CUPS supports several methods of auto-configuration via PPD keywords.
+
+
+
+
*APAutoSetupTool: "/LibraryPrinters/vendor/filename"
+
+
This deprecated keyword defines a program that sets the default option choices. It is run when a printer is added from the Add Printer window or the Nearby Printers list in the Print dialog.
+
+
The program is provided with two arguments: the printer's device URI and the PPD file to be used for the printer. The program must write an updated PPD file to stdout.
+
+
Note:
+
+This keyword is deprecated. New printer drivers SHOULD provide a CUPS command filter and support the "AutoConfigure" command. Alternately, drivers MAY use the SNMP OID keywords to configure network printers or PostScript query keywords to configure PostScript printers.
+
+
+
Examples:
+
+
+*% Use our setup tool when adding a printer
+*APAutoSetupTool: "/Library/Printers/vendor/Tools/autosetuptool"
+
+
+
+
+
*?MainKeyword: "
+ PostScript query code that writes a message using the = operator...
+"
+*End
+
+
The ?MainKeyword keyword defines PostScript code that determines the currently selected/enabled option keyword (choice) for the main keyword (option). It is typically used when communicating with USB, serial, Appletalk, and AppSocket (port 9100) printers.
+
+
The PostScript code typically sends its response back using the = operator.
+
+
Example:
+
+
+*OpenUI OptionDuplex/Duplexer Installed: Boolean
+*DuplexOptionDuplex: False
+*OptionDuplex False/Not Installed: ""
+*OptionDuplex True/Installed: ""
+
+*% Query the printer for the presence of the duplexer option...
+*?OptionDuplex: "
+ currentpagedevice /Duplex known
+ {(True)} {(False)} ifelse
+ = flush
+"
+*End
+*CloseUI: OptionDuplex
+
+
+
+
+
*?OIDMainKeyword: ".n.n.n..."
+*OIDMainKeyword OptionKeyword1: "value"
+...
+*OIDMainKeyword OptionKeywordN: "value"
+
+
The OIDMainKeyword keyword is used to define SNMP OIDs that map to installable options. The first (query) line defines the OID to lookup on the network device. The second and subsequent keywords define a mapping from OID value to option keyword. Since SNMP is an IP-based network protocol, this method is typically only used to configure AppSocket, IPP, and LPD network printers.
+
+
Examples:
+
+
+*% Get the installed memory on the printer...
+*?OIDInstalledMemory: ".1.3.6.1.2.1.25.2.2.0"
+*OIDInstalledMemory 16MB: "16384 KBytes"
+*OIDInstalledMemory 32MB: "32768 KBytes"
+*OIDInstalledMemory 48MB: "49152 KBytes"
+*OIDInstalledMemory 72MB: "73728 KBytes"
+
+
+
+
+
+
CUPS supports three types of color profiles. The first type is based on sRGB and is used by the standard CUPS raster filters and GPL Ghostscript. The second type is based on ICC profiles and is used by the Quartz-based filters on MacOS X. The final type is based on well-known colorspaces such as sRGB and Adobe RGB.
+
+
Note:
+
+At this time, none of the CUPS raster filters support ICC profiles. This will be addressed as time and resources permit.
+
+
+
+
+
+
*cupsColorProfile Resolution/MediaType: "density gamma m00 m01 m02 m10 m11 m12 m20 m21 m22"
+
+
This string keyword specifies an sRGB-based color profile consisting of gamma and density controls and a 3x3 CMY color transform matrix. This keyword is not supported on Mac OS X.
+
+
The Resolution and MediaType values may be "-" to act as a wildcard. Otherwise they must match one of the Resolution or MediaType option keywords defined in the PPD file.
+
+
The density and gamma values define gamma and
+density adjustment function such that:
+
+
+f(x) = density * x gamma
+
+
+
The m00 through m22 values define a 3x3 transformation matrix for the CMY color values. The density function is applied after the CMY transformation:
+
+
+| m00 m01 m02 |
+| m10 m11 m12 |
+| m20 m21 m22 |
+
+
+
Examples:
+
+
+*% Specify a profile for printing at 360dpi on all media types
+*cupsColorProfile 360dpi/-: "1.0 1.5 1.0 0.0 -0.2 -0.4 1.0 0.0 -0.2 0.0 1.0"
+
+*% Specify a profile for printing at 720dpi on Glossy media
+*cupsColorProfile 720dpi/Glossy: "1.0 2.5 1.0 0.0 -0.2 -0.4 1.0 0.0 -0.2 0.0 1.0"
+
+*% Specify a default profile for printing at all other resolutions and media types
+*cupsColorProfile -/-: "0.9 2.0 1.0 0.0 -0.2 -0.4 1.0 0.0 -0.2 0.0 1.0"
+
+
+
+
+
+
*cupsICCProfile ColorModel.MediaType.Resolution/Description: "filename"
+
+
This keyword specifies an ICC color profile that is used to convert the document colors to the device colorspace. The ColorModel, MediaType, and Resolution option keywords specify a selector for color profiles. If omitted, the color profile will match any option keyword for the corresponding main keyword.
+
+
The Description specifies human-readable text that is associated with the color profile. The filename portion specifies the ICC color profile to use; if the filename is not absolute, it is loaded relative to the /usr/share/cups/profiles directory.
+
+
Examples:
+
+
+*% Specify a profile for CMYK printing at 360dpi on all media types
+*cupsICCProfile CMYK..360dpi/360dpi CMYK: "/Library/Printers/vendor/Profiles/foo-360-cmyk.icc"
+
+*% Specify a profile for RGB printing at 720dpi on Glossy media
+*cupsColorProfile RGB.Glossy.720dpi/720dpi Glossy: "/Library/Printers/vendor/Profiles/foo-720-glossy-rgb.icc"
+
+*% Specify a default profile for printing at all other resolutions and media types
+*cupsICCProfile ../Default: "/Library/Printers/vendor/Profiles/foo-default.icc"
+
+
+
Customizing the Profile Selection Keywords
+
+
The MediaType and Resolution main keywords can be reassigned to different main keywords, allowing drivers to do color profile selection based on different parameters. The cupsICCQualifier2 and cupsICCQualifier3 keywords define the mapping from selector to main keyword:
+
+
+*cupsICCQualifier2: MainKeyword2
+*cupsICCQualifier3: MainKeyword3
+
+
+
The default mapping is as follows:
+
+
+*cupsICCQualifier2: MediaType
+*cupsICCQualifier3: Resolution
+
+
+
+
+
*APSupportsCustomColorMatching: true
+*APCustomColorMatchingName name/text: ""
+*APCustomColorMatchingProfile: profile
+*APDefaultCustomColorMatchingProfile: profile
+
+
These keywords tell the Mac OS X raster filters that the printer driver provides its own custom color matching and that generic color profiles should be used when generating 1-, 3-, and 4-component raster data as requested by the driver. The APCustomColorMatchingProfile and APDefaultColorMatchingProfile keywords specify alternate color profiles (sRGB or AdobeRGB) to use for 3-color (RGB) raster data.
+
+
Note:
+
+Prior to Mac OS X 10.6, the default RGB color space was Apple's "GenericRGB". The new default in Mac OS X 10.6 and later is "sRGB". For more information, see "Mac OS X v10.6: About gamma 2.2" on Apple's support site.
+
+
+
+
+
+
*APCustomColorMatchingName name/text: ""
+
+
This keyword defines an alternate name for the color matching provided by a driver in the Color Matching print panel. The default is to use the name "Vendor Matching" or its localized equivalent.
+
+
Examples:
+
+
+*% Define the names for our color matching...
+*APCustomColorMatchingName name/AcmeColor(tm): ""
+*fr.APCustomColorMatchingName name/La AcmeColor(tm): ""
+
+
+
+
+
*APCustomColorMatchingProfile: name
+
+
This keyword defines a supported RGB color profile that can be used when doing custom color matching. Currently only sRGB, AdobeRGB, and GenericRGB are supported. If not specified, RGB data will use the GenericRGB colorspace.
+
+
Note:
+
+If you provide multiple APCustomColorMatchingProfile keywords, you are responsible for providing the necessary user interface controls to select the profile in a print dialog pane. Add the named profile to the print settings using the key kPMCustomColorMatchingProfileKey.
+
+
+
+
Examples:
+
+
+*% Use sRGB for RGB color by default, but support both sRGB and AdobeRGB
+*APSupportsCustomColorMatching: true
+*APDefaultCustomColorMatchingProfile: sRGB
+*APCustomColorMatchingProfile: sRGB
+*APCustomColorMatchingProfile: AdobeRGB
+
+
+
+
+
*APDefaultCustomColorMatchingProfile: name
+
+
This keyword defines the default RGB color profile that will be used when doing custom color matching. Currently only sRGB, AdobeRGB, and GenericRGB are supported.
+
+
Examples:
+
+
+*% Use sRGB for RGB color by default
+*APSupportsCustomColorMatching: true
+*APDefaultCustomColorMatchingProfile: sRGB
+
+
+
+
+
*APSupportsCustomColorMatching: boolean
+
+
This keyword specifies that the driver provides its own custom color matching. When true, the default hand-off colorspace will be GenericGray, GenericRGB, or GenericCMYK depending on the number of components the driver requests. The APDefaultCustomColorMatchingProfile keyword can be used to override the default 3-component (RGB) colorspace.
+
+
The default for APSupportsCustomColorMatching is false.
+
+
Examples:
+
+
+*APSupportsCustomColorMatching: true
+*APDefaultCustomColorMatchingProfile: sRGB
+
+
+
+
+
+
Constraints are option choices that are not allowed by the driver or device, for example printing 2-sided transparencies. All versions of CUPS support constraints defined by the legacy Adobe UIConstraints and NonUIConstraints keywords which support conflicts between any two option choices, for example:
+
+
+*% Do not allow 2-sided printing on transparency media
+*UIConstraints: "*Duplex *MediaType Transparency"
+*UIConstraints: "*MediaType Transparency *Duplex"
+
+
+
While nearly all constraints can be expressed using these keywords, there are valid scenarios requiring constraints between more than two option choices. In addition, resolution of constraints is problematic since users and software have to guess how a particular constraint is best resolved.
+
+
CUPS 1.4 and higher define two new keywords for constraints, cupsUIConstraints and cupsUIResolver. Each cupsUIConstraints keyword points to a cupsUIResolver keyword which specifies alternate options that resolve the conflict condition. The same cupsUIResolver can be used by multiple cupsUIConstraints.
+
+
Note:
+
+When developing PPD files that contain constraints, it is very important to use the cupstestppd(1) program to verify that your constraints are accurate and cannot result in unresolvable option selections.
+
+
+
+
+
+
*cupsUIConstraints resolver: "*Keyword1 *Keyword2 ..."
+*cupsUIConstraints resolver: "*Keyword1 OptionKeyword1 *Keyword2 ..."
+*cupsUIConstraints resolver: "*Keyword1 *Keyword2 OptionKeyword2 ..."
+*cupsUIConstraints resolver: "*Keyword1 OptionKeyword1 *Keyword2 OptionKeyword2 ..."
+*cupsUIConstraints: "*InstallableKeyword1 OptionKeyword1 *Keyword2 OptionKeyword2 ..."
+
+
Lists two or more options which conflict. The "resolver" string is a (possibly unique) keyword which specifies which options to change when the constraint exists. When no resolver is provided, CUPS first tries the default choice followed by testing each option choice to resolve the conflict.
+
+
Examples:
+
+
+*% Specify that 2-sided printing cannot happen on transparencies
+*cupsUIConstraints transparency: "*Duplex *MediaType Transparency"
+
+*% Specify that envelope printing cannot happen from the paper trays
+*cupsUIConstraints envelope: "*PageSize Env10 *InputSlot Tray1"
+*cupsUIConstraints envelope: "*PageSize Env10 *InputSlot Tray1"
+*cupsUIConstraints envelope: "*PageSize EnvDL *InputSlot Tray2"
+*cupsUIConstraints envelope: "*PageSize EnvDL *InputSlot Tray2"
+
+*% Specify an installable option constraint for the envelope feeder
+*cupsUIConstraints: "*InputSlot EnvFeeder *InstalledEnvFeeder"
+
+*% Specify that photo printing cannot happen on plain paper or transparencies at 1200dpi
+*cupsUIConstraints photo: "*OutputMode Photo *MediaType Plain *Resolution 1200dpi"
+*cupsUIConstraints photo: "*OutputMode Photo *MediaType Transparency *Resolution 1200dpi"
+
+
+
+
+
*cupsUIResolution resolver: "*Keyword1 OptionKeyword1 *Keyword2 OptionKeyword2 ..."
+
+
Specifies two or more options to mark/select to resolve a constraint. The "resolver" string identifies a particular action to take for one or more cupsUIConstraints. The same action can be used for multiple constraints. The option keyword pairs are treated as an ordered list of option selections to try - only the first N selections will be used, where N is the minimum number of selections required. Because cupsResolveConflicts()
will not change the most recent option selection passed to it, at least two options from the constraints must be listed to avoid situations where conflicts cannot be resolved.
+
+
Examples:
+
+
+*% Specify the options to change for the 2-sided transparency constraint
+*cupsUIResolver transparency: "*Duplex None *MediaType Plain"
+
+*% Specify the options to change for the envelope printing constraints. Notice
+*% that we try to change the InputSlot to either the envelope feeder or the
+*% manual feed first, then we change the page size...
+*cupsUIResolver envelope: "*InputSlot EnvFeeder *InputSlot ManualFeed *PageSize Letter"
+
+*% Specify the options to change for the photo printing constraints
+*cupsUIResolver photo: "*OutputMode Best *Resolution 600dpi"
+
+
+
+
+
+
CUPS 1.2 and higher adds support for PPD files containing multiple languages by following the following additional rules:
+
+
+
+ - The LanguageVersion MUST be English
+
+ - The LanguageEncoding MUST be ISOLatin1
+
+ - The cupsLanguages keyword MUST be provided and list each of the supported locales in the PPD file
+
+ - Main and option keywords MUST NOT exceed 34 (instead of 40) characters to allow room for the locale prefixes in translation keywords
+
+ - The main keyword "Translation" MUST NOT be used
+
+ - Translation strings included with the main and option keywords MUST NOT contain characters outside the ASCII subset of ISOLatin1 and UTF-8; developers wishing to use characters outside ASCII MUST provide a separate set of English localization keywords for the affected keywords.
+
+ - Localizations are specified using a locale prefix of the form "ll" or "ll_CC." where "ll" is the 2-letter ISO language code and "CC" is the 2-letter ISO country code
+ - A generic language translation ("ll") SHOULD be provided with country-specific differences ("ll_CC") provided only as needed
+ - For historical reasons, the "zh" and "zh_CN" locales map to Simplified Chinese while the "zh_TW" locale maps to Traditional Chinese
+
+
+ - Locale-specific translation strings MUST be encoded using UTF-8.
+
+ - Main keywords MUST be localized using one of the following forms:
+
*ll.Translation MainKeyword/translation text: ""
+ *ll_CC.Translation MainKeyword/translation text: ""
+
+ - Option keywords MUST be localized using one of the following forms:
+
*ll.MainKeyword OptionKeyword/translation text: ""
+ *ll_CC.MainKeyword OptionKeyword/translation text: ""
+
+ - Localization keywords MAY appear anywhere after the first line of the PPD file
+
+
+
+
Note:
+
+We use a LanguageEncoding value of ISOLatin1 and limit the allowed base translation strings to ASCII to avoid character coding issues that would otherwise occur. In addition, requiring the base translation strings to be in English allows for easier fallback translation when no localization is provided in the PPD file for a given locale.
+
+
+
+
Examples:
+
+
+*LanguageVersion: English
+*LanguageEncoding: ISOLatin1
+*cupsLanguages: "de fr_CA"
+*ModelName: "Foobar Laser 9999"
+
+*% Localize ModelName for French and German
+*fr_CA.Translation ModelName/La Foobar Laser 9999: ""
+*de.Translation ModelName/Foobar LaserDrucken 9999: ""
+
+*cupsIPPReason com.vendor-error/A serious error occurred: "/help/com.vendor/error.html"
+*% Localize printer-state-reason for French and German
+*fr_CA.cupsIPPReason com.vendor-error/Une erreur sèrieuse s'est produite: "/help/com.vendor/error.html"
+*de.cupsIPPReason com.vendor-error/Eine ernste Störung trat: "/help/com.vendor/error.html"
+
+...
+
+*OpenUI *InputSlot/Paper Source: PickOne
+*OrderDependency: 10 AnySetup *InputSlot
+*DefaultInputSlot: Auto
+*% Localize InputSlot for French and German
+*fr_CA.Translation InputSlot/Papier source: ""
+*de.Translation InputSlot/Papiereinzug: ""
+*InputSlot Auto/Default: "<</ManualFeed false>>setpagedevice"
+*% Localize InputSlot=Auto for French and German
+*fr_CA.InputSlot Auto/Par Defaut: ""
+*de.InputSlot Auto/Standard: ""
+*InputSlot Manual/Manual Feed: "<</ManualFeed true>>setpagedevice"
+*% Localize InputSlot=Manual for French and German
+*fr_CA.InputSlot Manual/Manuel mecanisme de alimentation: ""
+*de.InputSlot Manual/Manueller Einzug: ""
+*CloseUI: *InputSlot
+
+
+
+
+
+
CUPS supports custom options using an extension of the CustomPageSize and ParamCustomPageSize syntax:
+
+
+*CustomFoo True: "command"
+*ParamCustomFoo Name1/Text 1: order type minimum maximum
+*ParamCustomFoo Name2/Text 2: order type minimum maximum
+...
+*ParamCustomFoo NameN/Text N: order type minimum maximum
+
+
+
When the base option is part of the JCLSetup section, the "command" string contains JCL commands with "\order" placeholders for each numbered parameter. The CUPS API handles any necessary value quoting for HP-PJL commands. For example, if the JCL command string is "@PJL SET PASSCODE=\1" and the first
+option value is "1234" then CUPS will output the string "@PJL SET PASSCODE=1234".
+
+
For non-JCLSetup options, the "order" value is a number from 1 to N and specifies the order of values as they are placed on the stack before the command. For example, if the PostScript command string is "<</cupsReal1 2 1 roll>>setpagedevice" and the option value is "2.0" then CUPS will output the string "2.0 <</cupsReal1 2 1 roll>>setpagedevice".
+
+
The "type" is one of the following keywords:
+
+
+
+ - curve - a real value from "minimum" to "maximum" representing a gamma correction curve using the function: f(x) = x value
+
+ - int - an integer value from "minimum" to "maximum"
+
+ - invcurve - a real value from "minimum" to "maximum" representing a gamma correction curve using the function: f(x) = x 1 / value
+
+ - passcode - a string of numbers value with a minimum of "minimum" numbers and a maximum of "maximum" numbers ("minimum" and "maximum" are numbers and passcode strings are not displayed in the user interface)
+
+ - password - a string value with a minimum of "minimum" characters and a maximum of "maximum" characters ("minimum" and "maximum" are numbers and password strings are not displayed in the user interface)
+
+ - points - a measurement value in points from "minimum" to "maximum"
+
+ - real - a real value from "minimum" to "maximum"
+
+ - string - a string value with a minimum of "minimum" characters and a maximum of "maximum" characters ("minimum" and "maximum" are numbers)
+
+
+
+
Examples:
+
+
+*% Base JCL key code option
+*JCLOpenUI JCLPasscode/Key Code: PickOne
+*OrderDependency: 10 JCLSetup *JCLPasscode
+*DefaultJCLPasscode: None
+*JCLPasscode None/No Code: ""
+*JCLPasscode 1111: "@PJL SET PASSCODE = 1111<0A>"
+*JCLPasscode 2222: "@PJL SET PASSCODE = 2222<0A>"
+*JCLPasscode 3333: "@PJL SET PASSCODE = 3333<0A>"
+*JCLCloseUI: *JCLPasscode
+
+*% Custom JCL key code option
+*CustomJCLPasscode True: "@PJL SET PASSCODE = \1<0A>"
+*ParamCustomJCLPasscode Code/Key Code: 1 passcode 4 4
+
+
+*% Base PostScript watermark option
+*OpenUI WatermarkText/Watermark Text: PickOne
+*OrderDependency: 10 AnySetup *WatermarkText
+*DefaultWatermarkText: None
+*WatermarkText None: ""
+*WatermarkText Draft: "<</cupsString1(Draft)>>setpagedevice"
+*CloseUI: *WatermarkText
+
+*% Custom PostScript watermark option
+*CustomWatermarkText True: "<</cupsString1 3 -1 roll>>setpagedevice"
+*ParamCustomWatermarkText Text: 1 string 0 32
+
+
+*% Base PostScript gamma/density option
+*OpenUI GammaDensity/Gamma and Density: PickOne
+*OrderDependency: 10 AnySetup *GammaDensity
+*DefaultGammaDensity: Normal
+*GammaDensity Normal/Normal: "<</cupsReal1 1.0/cupsReal2 1.0>>setpagedevice"
+*GammaDensity Light/Lighter: "<</cupsReal1 0.9/cupsReal2 0.67>>setpagedevice"
+*GammaDensity Dark/Darker: "<</cupsReal1 1.1/cupsReal2 1.5>>setpagedevice"
+*CloseUI: *GammaDensity
+
+*% Custom PostScript gamma/density option
+*CustomGammaDensity True: "<</cupsReal1 3 -1 roll/cupsReal2 5 -1>>setpagedevice"
+*ParamCustomGammaDensity Gamma: 1 curve 0.1 10
+*ParamCustomGammaDensity Density: 2 real 0 2
+
+
+
+
+
+
PPD files are used for both PostScript and non-PostScript printers. For CUPS raster drivers, you use a subset of the PostScript language to set page device keywords such as page size, resolution, and so forth. For example, the following code sets the page size to A4 size:
+
+
+*PageSize A4: "<</PageSize[595 842]>>setpagedevice"
+
+
+
Custom options typically use other operators to organize the values into a key/value dictionary for setpagedevice. For example, our previous CustomWatermarkText option code uses the roll operator to move the custom string value into the dictionary for setpagedevice:
+
+
+*CustomWatermarkText True: "<</cupsString1 3 -1 roll>>setpagedevice"
+
+
+
For a custom string value of "My Watermark", CUPS will produce the following PostScript code for the option:
+
+
+(My Watermark)
+<</cupsString1 3 -1 roll>>setpagedevice
+
+
+
The code moves the string value ("My Watermark") from the bottom of the stack to the top, creating a dictionary that looks like:
+
+
+<</cupsString1(My Watermark)>>setpagedevice
+
+
+
The resulting dictionary sets the page device attributes that are sent to your raster driver in the page header.
+
+
Custom Page Size Code
+
+
There are many possible implementations of the CustomPageSize code. For CUPS raster drivers, the following code is recommended:
+
+
+*ParamCustomPageSize Width: 1 points min-width max-width
+*ParamCustomPageSize Height: 2 points min-height max-height
+*ParamCustomPageSize WidthOffset: 3 points 0 0
+*ParamCustomPageSize HeightOffset: 4 points 0 0
+*ParamCustomPageSize Orientation: 5 int 0 0
+*CustomPageSize True: "pop pop pop <</PageSize[5 -2 roll]/ImagingBBox null>>setpagedevice"
+
+
+
Supported PostScript Operators
+
+
CUPS supports the following PostScript operators in addition to the usual PostScript number, string (literal and hex-encoded), boolean, null, and name values:
+
+
+
+ - << - Start a dictionary.
+
+ - >> - End a dictionary.
+
+ - [ - Start an array.
+
+ - ] - End an array.
+
+ - copy - Copy the top N objects on the stack.
+
+ - dup - Copy the top object on the stack.
+
+ - index - Copy the Nth from the top object on the stack.
+
+ - pop - Pop the top object on the stack.
+
+ - roll - Shift the top N objects on the stack.
+
+ - setpagedevice - Set the page header values according to the key/value dictionary on the stack.
+
+
+
+
Note:
+
+Never use the unsupported dict or put
+operators in your option code. These operators are typically used in
+option code dating back to Level 1 PostScript printers, which did not
+support the simpler << or >> operators.
+If you have old option code using dict or put, you can
+rewrite it very easily to use the newer << and
+>> operators instead. For example, the following code
+to set the page size:
+
+
+
+
+1 dict dup /PageSize [612 792] put setpagedevice
+
+
+can be rewritten as:
+
+
+<< /PageSize [612 792] >> setpagedevice
+
+
+
+
+
Supported Page Device Attributes
+
+
Table 2 shows the supported page device attributes along with PostScript code examples.
+
+
+
+Table 2: Supported Page Device Attributes
+
+
+ Name(s) |
+ Type |
+ Description |
+ Example(s) |
+
+
+
+
+ AdvanceDistance |
+ Integer |
+ Specifies the number of points to advance roll media after printing. |
+ <</AdvanceDistance 18>>setpagedevice |
+
+
+ AdvanceMedia |
+ Integer |
+ Specifies when to advance the media: 0 = never, 1 = after the file, 2 = after the job, 3 = after the set, and 4 = after the page. |
+ <</AdvanceMedia 4>>setpagedevice |
+
+
+ Collate |
+ Boolean |
+ Specifies whether collated copies are required. |
+ <</Collate true>>setpagedevice |
+
+
+ CutMedia |
+ Integer |
+ Specifies when to cut the media: 0 = never, 1 = after the file, 2 = after the job, 3 = after the set, and 4 = after the page. |
+ <</CutMedia 1>>setpagedevice |
+
+
+ Duplex |
+ Boolean |
+ Specifies whether 2-sided printing is required. |
+ <</Duplex true>>setpagedevice |
+
+
+ HWResolution |
+ Integer Array |
+ Specifies the resolution of the page image in pixels per inch. |
+ <</HWResolution[1200 1200]>>setpagedevice |
+
+
+ InsertSheet |
+ Boolean |
+ Specifies whether to insert a blank sheet before the job. |
+ <</InsertSheet true>>setpagedevice |
+
+
+ Jog |
+ Integer |
+ Specifies when to shift the media in the output bin: 0 = never, 1 = after the file, 2 = after the job, 3 = after the set, and 4 = after the page. |
+ <</Jog 2>>setpagedevice |
+
+
+ LeadingEdge |
+ Integer |
+ Specifies the leading edge of the media: 0 = top, 1 = right, 2 = bottom, 3 = left. |
+ <</LeadingEdge 0>>setpagedevice |
+
+
+ ManualFeed |
+ Boolean |
+ Specifies whether media should be drawn from the manual feed tray. Note: The MediaPosition attribute is preferred over the ManualFeed attribute. |
+ <</ManualFeed true>>setpagedevice |
+
+
+ MediaClass |
+ String |
+ Specifies a named media. |
+ <</MediaClass (Invoices)>>setpagedevice |
+
+
+ MediaColor |
+ String |
+ Specifies the color of the media. |
+ <</MediaColor >>setpagedevice |
+
+
+ MediaPosition |
+ Integer |
+ Specifies the tray or source of the media. |
+ <</MediaPosition 12>>setpagedevice |
+
+
+ MediaType |
+ String |
+ Specifies the general media type. |
+ <</MediaType (Glossy)>>setpagedevice |
+
+
+ MediaWeight |
+ Integer |
+ Specifies the media weight in grams per meter2. |
+ <</MediaWeight 100>>setpagedevice |
+
+
+ MirrorPrint |
+ Boolean |
+ Specifies whether to flip the output image horizontally. |
+ <</MirrorPrint true>>setpagedevice |
+
+
+ NegativePrint |
+ Boolean |
+ Specifies whether to invert the output image. |
+ <</NegativePrint true>>setpagedevice |
+
+
+ NumCopies |
+ Integer |
+ Specifies the number of copies to produce of each page. |
+ <</NumCopies 100>>setpagedevice |
+
+
+ Orientation |
+ Integer |
+ Specifies the orientation of the output: 0 = portrait, 1 = landscape rotated counter-clockwise, 2 = upside-down, 3 = landscape rotated clockwise. |
+ <</Orientation 3>>setpagedevice |
+
+
+ OutputFaceUp |
+ Boolean |
+ Specifies whether to place the media face-up in the output bin/tray. |
+ <</OutputFaceUp true>>setpagedevice |
+
+
+ OutputType |
+ String |
+ Specifies the output type name. |
+ <</OutputType (Photo)>>setpagedevice |
+
+
+ PageSize |
+ Integer/Real Array |
+ Specifies the width and length/height of the page in points. |
+ <</PageSize[595 842]>>setpagedevice |
+
+
+ Separations |
+ Boolean |
+ Specifies whether to produce color separations. |
+ <</Separations true>>setpagedevice |
+
+
+ TraySwitch |
+ Boolean |
+ Specifies whether to switch trays automatically. |
+ <</TraySwitch true>>setpagedevice |
+
+
+ Tumble |
+ Boolean |
+ Specifies whether the back sides of pages are rotated 180 degrees. |
+ <</Tumble true>>setpagedevice |
+
+
+ cupsBorderlessScalingFactor |
+ Real |
+ Specifies the amount to scale the page image dimensions. |
+ <</cupsBorderlessScalingFactor 1.01>>setpagedevice |
+
+
+ cupsColorOrder |
+ Integer |
+ Specifies the order of colors: 0 = chunked, 1 = banded, 2 = planar. |
+ <</cupsColorOrder 0>>setpagedevice |
+
+
+ cupsColorSpace |
+ Integer |
+ Specifies the page image colorspace: 0 = W, 1 = RGB, 2 = RGBA, 3 = K, 4 = CMY, 5 = YMC, 6 = CMYK, 7 = YMCK, 8 = KCMY, 9 = KCMYcm, 10 = GMCK, 11 = GMCS, 12 = White, 13 = Gold, 14 = Silver, 15 = CIE XYZ, 16 = CIE Lab, 17 = RGBW, 32 to 46 = CIE Lab (1 to 15 inks) |
+ <</cupsColorSpace 1 >>setpagedevice |
+
+
+ cupsCompression |
+ Integer |
+ Specifies a driver compression type/mode. |
+ <</cupsCompression 2>>setpagedevice |
+
+
+ cupsInteger0
+ ...
+ cupsInteger15 |
+ Integer |
+ Specifies driver integer values. |
+ <</cupsInteger11 1234>>setpagedevice |
+
+
+ cupsMarkerType |
+ String |
+ Specifies the type of ink/toner to use. |
+ <</cupsMarkerType (Black+Color)>>setpagedevice |
+
+
+ cupsMediaType |
+ Integer |
+ Specifies a numeric media type. |
+ <</cupsMediaType 999>>setpagedevice |
+
+
+ cupsPageSizeName |
+ String |
+ Specifies the name of the page size. |
+ <</cupsPageSizeName (A4.Full)>>setpagedevice |
+
+
+ cupsPreferredBitsPerColor |
+ Integer |
+ Specifies the preferred number of bits per color, typically 8 or 16. |
+ <</cupsPreferredBitsPerColor 16>>setpagedevice |
+
+
+ cupsReal0
+ ...
+ cupsReal15 |
+ Real |
+ Specifies driver real number values. |
+ <</cupsReal15 1.234>>setpagedevice |
+
+
+ cupsRenderingIntent |
+ String |
+ Specifies the color rendering intent. |
+ <</cupsRenderingIntent (AbsoluteColorimetric)>>setpagedevice |
+
+
+ cupsRowCount |
+ Integer |
+ Specifies the number of rows of raster data to print on each line for some drivers. |
+ <</cupsRowCount 24>>setpagedevice |
+
+
+ cupsRowFeed |
+ Integer |
+ Specifies the number of rows to feed between passes for some drivers. |
+ <</cupsRowFeed 17>>setpagedevice |
+
+
+ cupsRowStep |
+ Integer |
+ Specifies the number of lines between columns/rows on the print head for some drivers. |
+ <</cupsRowStep 2>>setpagedevice |
+
+
+ cupsString0
+ ...
+ cupsString15 |
+ String |
+ Specifies driver string values. |
+ <</cupsString0(String Value)>>setpagedevice |
+
+
+
+
+
+
+
+
The CUPS media keywords allow drivers to specify alternate custom page
+size limits based on up to two options.
+
+
+
+
*cupsMediaQualifier2: MainKeyword
+
+
This keyword specifies the second option to use for overriding the
+custom page size limits.
+
+
Example:
+
+
+*% Specify alternate custom page size limits based on InputSlot and Quality
+*cupsMediaQualifier2: InputSlot
+*cupsMediaQualifier3: Quality
+*cupsMaxSize .Manual.: "1000 1000"
+*cupsMinSize .Manual.: "100 100"
+*cupsMinSize .Manual.Photo: "200 200"
+*cupsMinSize ..Photo: "300 300"
+
+
+
+
+
*cupsMediaQualifier3: MainKeyword
+
+
This keyword specifies the third option to use for overriding the
+custom page size limits.
+
+
Example:
+
+
+*% Specify alternate custom page size limits based on InputSlot and Quality
+*cupsMediaQualifier2: InputSlot
+*cupsMediaQualifier3: Quality
+*cupsMaxSize .Manual.: "1000 1000"
+*cupsMinSize .Manual.: "100 100"
+*cupsMinSize .Manual.Photo: "200 200"
+*cupsMinSize ..Photo: "300 300"
+
+
+
+
+
*cupsMinSize .Qualifier2.Qualifier3: "width length"
+*cupsMinSize .Qualifier2.: "width length"
+*cupsMinSize ..Qualifier3: "width length"
+
+
This keyword specifies alternate minimum custom page sizes in points.
+The cupsMediaQualifier2 and
+cupsMediaQualifier3 keywords
+are used to identify options to use for matching.
+
+
Example:
+
+
+*% Specify alternate custom page size limits based on InputSlot and Quality
+*cupsMediaQualifier2: InputSlot
+*cupsMediaQualifier3: Quality
+*cupsMaxSize .Manual.: "1000 1000"
+*cupsMinSize .Manual.: "100 100"
+*cupsMinSize .Manual.Photo: "200 200"
+*cupsMinSize ..Photo: "300 300"
+
+
+
+
+
*cupsMaxSize .Qualifier2.Qualifier3: "width length"
+*cupsMaxSize .Qualifier2.: "width length"
+*cupsMaxSize ..Qualifier3: "width length"
+
+
This keyword specifies alternate maximum custom page sizes in points.
+The cupsMediaQualifier2 and
+cupsMediaQualifier3 keywords
+are used to identify options to use for matching.
+
+
Example:
+
+
+*% Specify alternate custom page size limits based on InputSlot and Quality
+*cupsMediaQualifier2: InputSlot
+*cupsMediaQualifier3: Quality
+*cupsMaxSize .Manual.: "1000 1000"
+*cupsMinSize .Manual.: "100 100"
+*cupsMinSize .Manual.Photo: "200 200"
+*cupsMinSize ..Photo: "300 300"
+
+
+
+
+
+
+
+
*cupsBackSide: keyword
+
+
This keyword requests special handling of the back side of pages
+when doing duplexed (2-sided) output. Table 1
+shows the supported keyword values for this keyword and their effect
+on the raster data sent to your driver. For example, when cupsBackSide
+is Rotated
and Tumble is false, your driver
+will receive print data starting at the bottom right corner of the page, with
+each line going right-to-left instead of left-to-right. The default value is
+Normal
.
+
+
Note:
+
+cupsBackSide replaces the older cupsFlipDuplex
+keyword - if cupsBackSide is specified, cupsFlipDuplex
+will be ignored.
+
+
+
+
+
+Table 1: Back Side Raster Coordinate System
+
+
+ cupsBackSide |
+ Tumble Value |
+ Image Presentation |
+
+
+
+
+ Normal |
+ false |
+ Left-to-right, top-to-bottom |
+
+
+ Normal |
+ true |
+ Left-to-right, top-to-bottom |
+
+
+ ManualTumble |
+ false |
+ Left-to-right, top-to-bottom |
+
+
+ ManualTumble |
+ true |
+ Right-to-left, bottom-to-top |
+
+
+ Rotated |
+ false |
+ Right-to-left, bottom-to-top |
+
+
+ Rotated |
+ true |
+ Right-to-left, top-to-bottom |
+
+
+ Flipped * |
+ false |
+ Left-to-right, bottom-to-top |
+
+
+ Flipped * |
+ true |
+ Right-to-left, top-to-bottom |
+
+
+
+
+
+
* - Not supported in Mac OS X 10.5.x and earlier
+
+
+
+
Examples:
+
+
+*% Flip the page image for the back side of duplexed output
+*cupsBackSide: Flipped
+
+*% Rotate the page image for the back side of duplexed output
+*cupsBackSide: Rotated
+
+
+
Also see the related APDuplexRequiresFlippedMargin
+keyword.
+
+
+
+
*cupsCommands: "name name2 ... nameN"
+
+
This string keyword specifies the commands that are supported by the
+CUPS command file filter for this device. The command names are separated
+by whitespace.
+
+
Example:
+
+
+*% Specify the list of commands we support
+*cupsCommands: "AutoConfigure Clean PrintSelfTestPage ReportLevels com.vendor.foo"
+
+
+
+
+
+
*cupsEvenDuplex: boolean
+
+
This boolean keyword notifies the RIP filters that the
+destination printer requires an even number of pages when 2-sided
+printing is selected. The default value is false
.
+
+
Example:
+
+
+*% Always send an even number of pages when duplexing
+*cupsEvenDuplex: true
+
+
+
+
+
*cupsFax: boolean
+
+
This boolean keyword specifies whether the PPD defines a facsimile device. The default is false.
+
+
Examples:
+
+
+*cupsFax: true
+
+
+
+
+
*cupsFilter: "source/type cost program"
+
+
This string keyword provides a conversion rule from the
+given source type to the printer's native format using the
+filter "program". If a printer supports the source type directly,
+the special filter program "-" may be specified.
+
+
Examples:
+
+
+*% Standard raster printer driver filter
+*cupsFilter: "application/vnd.cups-raster 100 rastertofoo"
+
+*% Plain text filter
+*cupsFilter: "text/plain 10 texttofoo"
+
+*% Pass-through filter for PostScript printers
+*cupsFilter: "application/vnd.cups-postscript 0 -"
+
+
+
+
+
*cupsFlipDuplex: boolean
+
+
Due to implementation differences between Mac OS X and Ghostscript,
+the cupsFlipDuplex keyword is deprecated. Instead, use
+the cupsBackSide keyword to specify
+the coordinate system (pixel layout) of the page data on the back side of
+duplex pages.
+
+
The value true
maps to a cupsBackSide value
+of Rotated
on Mac OS X and Flipped
with
+Ghostscript.
+
+
The default value is false
.
+
+
Note:
+
+Mac OS X drivers that previously used
+cupsFlipDuplex may wish to provide both the old and
+new keywords for maximum compatibility, for example:
+
+
+*cupsBackSide: Rotated
+*cupsFlipDuplex: true
+
+
+Similarly, drivers written for other operating systems using
+Ghostscript can use:
+
+
+*cupsBackSide: Flipped
+*cupsFlipDuplex: true
+
+
+
+
+
*cupsIPPFinishings number/text: "*Option Choice ..."
+
+
This keyword defines a mapping from IPP finishings
+values to PPD options and choices.
+
+
Examples:
+
+
+*cupsIPPFinishings 4/staple: "*StapleLocation SinglePortrait"
+*cupsIPPFinishings 5/punch: "*PunchMedia Yes *PunchLocation LeftSide"
+*cupsIPPFinishings 20/staple-top-left: "*StapleLocation SinglePortrait"
+*cupsIPPFinishings 21/staple-bottom-left: "*StapleLocation SingleLandscape"
+
+
+
+
+
*cupsIPPReason reason/Reason Text: "optional URIs"
+
+
This optional keyword maps custom
+printer-state-reasons
keywords that are generated by
+the driver to human readable text. The optional URIs string
+contains zero or more URIs separated by a newline. Each URI can
+be a CUPS server absolute path to a help file under the
+scheduler's DocumentRoot
directory, a full HTTP URL
+("http://www.domain.com/path/to/help/page.html"), or any other
+valid URI which directs the user at additional information
+concerning the condition that is being reported.
+
+
Since the reason text is limited to 80 characters by the PPD specification,
+longer text strings can be included by URI-encoding the text with the "text"
+scheme, for example "text:some%20text". Multiple text
URIs are
+combined (with spaces between each URI) by the ppdLocalizeIPPReason
+into a single string that can be displayed to the user.
+
+
Examples:
+
+
+*% Map com.vendor-error to text but no page
+*cupsIPPReason com.vendor-error/A serious error occurred: ""
+
+*% Map com.vendor-error to more than 80 characters of text but no page
+*cupsIPPReason com.vendor-error/A serious error occurred: "text:Now%20is%20the%20time
+text:for%20all%20good%20men%20to%20come%20to%20the%20aid%20of%20their%20country."
+
+*% Map com.vendor-error to text and a local page
+*cupsIPPReason com.vendor-error/A serious error occurred: "/help/com.vendor/error.html"
+
+*% Map com.vendor-error to text and a remote page
+*cupsIPPReason com.vendor-error/A serious error occurred: "http://www.vendor.com/help"
+
+*% Map com.vendor-error to text and a local, Apple help book, and remote page
+*APHelpBook: "file:///Library/Printers/vendor/Help.bundle"
+*cupsIPPReason com.vendor-error/A serious error occurred: "/help/com.vendor/error.html
+help:anchor='com.vendor-error'%20bookID=Vendor%20Help
+http://www.vendor.com/help"
+*End
+
+
+
+
+
*cupsLanguages: "locale list"
+
+
This keyword describes which language localizations are
+included in the PPD. The "locale list" string is a space-delimited
+list of locale names ("en", "en_US", "fr_CA", etc.)
+
+
Example:
+
+
+*% Specify Canadian, UK, and US English, and Candian and French French
+*cupsLanguages: "en_CA en_UK en_US fr_CA fr_FR"
+
+
+
+
+
*cupsManualCopies: boolean
+
+
This boolean keyword notifies the RIP filters that the
+destination printer does not support copy generation in
+hardware. The default value is false
.
+
+
Example:
+
+
+*% Tell the RIP filters to generate the copies for us
+*cupsManualCopies: true
+
+
+
+
+
*cupsMarkerName/Name Text: ""
+
+
This optional keyword maps marker-names
strings that are
+generated by the driver to human readable text.
+
+
Examples:
+
+
+*% Map cyanToner to "Cyan Toner"
+*cupsMarkerName cyanToner/Cyan Toner: ""
+
+
+
+
+
*cupsMarkerNotice: "disclaimer text"
+
+
This optional keyword provides disclaimer text for the supply level
+information provided by the driver, typically something like "supply levels
+are approximate".
+
+
Examples:
+
+
+*cupsMarkerNotice: "Supply levels are approximate."
+
+
+
+
+
*cupsModelNumber: number
+
+
This integer keyword specifies a printer-specific model
+number. This number can be used by a filter program to adjust
+the output for a specific model of printer.
+
+
Example:
+
+
+*% Specify an integer for a driver-specific model number
+*cupsModelNumber: 1234
+
+
+
+
+
*cupsPJLCharset: "ISO character set name"
+
+
This string keyword specifies the character set that is used
+for strings in PJL commands. If not specified, US-ASCII is
+assumed.
+
+
Example:
+
+
+*% Specify UTF-8 is used in PJL strings
+*cupsPJLCharset: "UTF-8"
+
+
+
+
+
*cupsPJLDisplay: "what"
+
+
This optional keyword specifies which command is used to display the
+job ID, name, and user on the printer's control panel. "What" is either "none"
+to disable this functionality, "job" to use "@PJL JOB DISPLAY", or "rdymsg"
+to use "@PJL RDYMSG DISPLAY". The default is "job".
+
+
Examples:
+
+
+*% Display job information using @PJL SET RDYMSG DISPLAY="foo"
+*cupsPJLDisplay: "rdymsg"
+
+*% Display job information display
+*cupsPJLDisplay: "none"
+
+
+
+
+
*cupsPortMonitor urischeme/Descriptive Text: "port monitor"
+
+
This string keyword specifies printer-specific "port
+monitor" filters that may be used with the printer. The CUPS
+scheduler also looks for the Protocols keyword to see
+if the BCP or TBCP protocols are supported. If
+so, the corresponding port monitor ("bcp" and "tbcp",
+respectively) is listed in the printer's
+port-monitor-supported keyword.
+
+
The "urischeme" portion of the keyword specifies the URI scheme
+that this port monitor should be used for. Typically this is used to
+pre-select a particular port monitor for each type of connection that
+is supported by the printer. The "port monitor" string can be "none"
+to disable the port monitor for the given URI scheme.
+
+
Examples:
+
+
+*% Specify a PostScript printer that supports the TBCP protocol
+*Protocols: TBCP PJL
+
+*% Specify that TBCP should be used for socket connections but not USB
+*cupsPortMonitor socket/AppSocket Printing: "tbcp"
+*cupsPortMonitor usb/USB Printing: "none"
+
+*% Specify a printer-specific port monitor for an Epson USB printer
+*cupsPortMonitor usb/USB Status Monitor: "epson-usb"
+
+
+
+
+
*cupsPreFilter: "source/type cost program"
+
+
This string keyword provides a pre-filter rule. The pre-filter
+program will be inserted in the conversion chain immediately
+before the filter that accepts the given MIME type.
+
+
Examples:
+
+
+*% PDF pre-filter
+*cupsPreFilter: "application/pdf 100 mypdfprefilter"
+
+*% PNG pre-filter
+*cupsPreFilter: "image/png 0 mypngprefilter"
+
+
+
+
+
+
*cupsPrintQuality keyword/text: "code"
+
+
This UI keyword defines standard print qualities that directly map from the IPP "print-quality" job template keyword. Standard keyword values are "Draft", "Normal", and "High" which are mapped from the IPP "print-quality" values 3, 4, and 5 respectively. Each cupsPrintQuality
option typically sets output mode and resolution parameters in the page device dictionary, eliminating the need for separate (and sometimes confusing) output mode and resolution options.
+
+
Note:
+
+Unlike all of the other keywords defined in this document, cupsPrintQuality
is a UI keyword that MUST be enclosed inside the PPD OpenUI
and CloseUI
keywords.
+
+
+
+
Examples:
+
+
+*OpenUI *cupsPrintQuality/Print Quality: PickOne
+*OrderDependency: 10 AnySetup *cupsPrintQuality
+*DefaultcupsPrintQuality: Normal
+*cupsPrintQuality Draft/Draft: "code"
+*cupsPrintQuality Normal/Normal: "code"
+*cupsPrintQuality High/Photo: "code"
+*CloseUI: *cupsPrintQuality
+
+
+
+
+
*cupsSNMPSupplies: boolean
+
+
This keyword tells the standard network backends whether they should query
+the standard SNMP Printer MIB OIDs for supply levels. The default value is
+True
.
+
+
Example:
+
+
+*% Do not use SNMP queries to report supply levels
+*cupsSNMPSupplies: False
+
+
+
+
+
*cupsVersion: major.minor
+
+
This required keyword describes which version of the CUPS
+PPD file extensions was used. Currently it must be the string
+"1.0", "1.1", "1.2", or "1.3".
+
+
Example:
+
+
+*% Specify a CUPS 1.2 driver
+*cupsVersion: "1.2"
+
+
+
+
+
+
+
+
*APDialogExtension: "/Library/Printers/vendor/filename.plugin"
+
+
This keyword defines additional option panes that are displayed in the
+print dialog. Each keyword adds one or more option panes. See the "OutputBinsPDE"
+example and Apple
+Technical Q&A QA1352 for information on writing your own print dialog
+plug-ins.
+
+
Note:
+
+Starting with Mac OS X 10.5, each plug-in must be compiled "4-way fat"
+(32-bit and 64-bit for both PowerPC and Intel) with garbage collection enabled
+in order to be usable with all applications.
+
+
+
+
Examples:
+
+
+*% Add two panes for finishing and driver options
+*APDialogExtension: "/Library/Printers/vendor/finishing.plugin"
+*APDialogExtension: "/Library/Printers/vendor/options.plugin"
+
+
+
+
+
*APDuplexRequiresFlippedMargin: boolean
+
+
This boolean keyword notifies the RIP filters that the
+destination printer requires the top and bottom margins of the
+ImageableArea to be swapped for the back page. The
+default is true when cupsBackSide is Flipped
+and false otherwise. Table 2 shows how
+APDuplexRequiresFlippedMargin interacts with cupsBackSide
+and the Tumble page attribute.
+
+
+
+Table 2: Margin Flipping Modes
+
+
+ APDuplexRequiresFlippedMargin |
+ cupsBackSide |
+ Tumble Value |
+ Margins |
+
+
+
+
+ false |
+ any |
+ any |
+ Normal |
+
+
+ any |
+ Normal |
+ any |
+ Normal |
+
+
+ true |
+ ManualDuplex |
+ false |
+ Normal |
+
+
+ true |
+ ManualDuplex |
+ true |
+ Flipped |
+
+
+ true |
+ Rotated |
+ false |
+ Flipped |
+
+
+ true |
+ Rotated |
+ true |
+ Normal |
+
+
+ true or unspecified |
+ Flipped |
+ any |
+ Flipped |
+
+
+
+
+
Example:
+
+
+*% Rotate the back side images
+*cupsBackSide: Rotated
+
+*% Don't swap the top and bottom margins for the back side
+*APDuplexRequiresFlippedMargin: false
+
+
+
Also see the related cupsBackSide
+keyword.
+
+
+
+
*APHelpBook: "bundle URL"
+
+
This string keyword specifies the Apple help book bundle to use when
+looking up IPP reason codes for this printer driver. The
+cupsIPPReason keyword maps
+"help" URIs to this file.
+
+
Example:
+
+
+*APHelpBook: "file:///Library/Printers/vendor/Help.bundle"
+
+
+
+
+
*APICADriver: boolean
+
+
This keyword specifies whether the device has a matching Image Capture
+Architecture (ICA) driver for scanning. The default is False.
+
+
Examples:
+
+
+*APICADriver: True
+*APScanAppBundleID: "com.apple.ImageCaptureApp"
+
+
+
+
+
*APPrinterIconPath: "/Library/Printers/vendor/filename.icns"
+
+
This keyword defines the location of a printer icon file to use when
+displaying the printer. The file must be in the Apple icon format.
+
+
Examples:
+
+
+*% Apple icon file
+*APPrinterIconPath: "/Library/Printers/vendor/Icons/filename.icns"
+
+
+
+
+
*APPrinterLowInkTool: "/Library/Printers/vendor/program"
+
+
This keyword defines an program that checks the ink/toner/marker levels
+on a printer, returning an XML document with those levels. See the "InkTool"
+example and
+Apple
+Technical Note TN2144 for more information.
+
+
Examples:
+
+
+*% Use a vendor monitoring program
+*APPrinterLowInkTool: "/Library/Printers/vendor/Tools/lowinktool"
+
+
+
+
+
*APPrinterPreset name/text: "*Option Choice ..."
+
+
This keyword defines presets for multiple options that show up
+in the print dialog of applications (such as iPhoto) that set the job
+style hint to NSPrintPhotoJobStyleHint. Each preset maps to one or
+more pairs of PPD options and choices as well as providing key/value data for
+the application. The following standard preset names are currently defined:
+
+
+
+ General_with_Paper_Auto-Detect
; Normal quality general printing with auto-detected media.
+
+ General_with_Paper_Auto-Detect_-_Draft
; Draft quality general printing with auto-detected media.
+
+ General_on_Plain_Paper
; Normal quality general printing on plain paper.
+
+ General_on_Plain_Paper_-_Draft
; Draft quality general printing on plain paper.
+
+ Photo_with_Paper_Auto-Detect
; Normal quality photo printing with auto-detected media.
+
+ Photo_with_Paper_Auto-Detect_-_Fine
; High quality photo printing with auto-detected media.
+
+ Photo_on_Plain_Paper
; Normal quality photo printing on plain paper.
+
+ Photo_on_Plain_Paper_-_Fine
; High quality photo printing on plain paper.
+
+ Photo_on_Photo_Paper
; Normal quality photo printing on glossy photo paper.
+
+ Photo_on_Photo_Paper_-_Fine
; High quality photo printing on glossy photo paper.
+
+ Photo_on_Matte_Paper
; Normal quality photo printing on matte paper.
+
+ Photo_on_Matte_Paper_-_Fine
; High quality photo printing on matte paper.
+
+
+
+
The value string consists of pairs of keywords, either an option name and
+choice (*MainKeyword OptionKeyword) or a preset identifier and value
+(com.apple.print.preset.foo value). The following preset identifiers are currently used:
+
+
+
+ com.apple.print.preset.graphicsType
; specifies the type of printing used for this printing - "General" for general purpose printing and "Photo" for photo printing.
+
+ com.apple.print.preset.media-front-coating
; specifies the media type selected by this preset - "none" (plain paper), "glossy", "high-gloss", "semi-gloss", "satin", "matte", and "autodetect".
+
+ com.apple.print.preset.output-mode
; specifies the output mode for this preset - "color" (default for color printers) or "monochrome" (grayscale, default for B&W printers).
+
+ com.apple.print.preset.quality
; specifies the overall print quality selected by this preset - "low" (draft), "mid" (normal), or "high".
+
+
+
+
Presets, like options, can also be localized in multiple languages.
+
+
Examples:
+
+
+*APPrinterPreset Photo_on_Photo_Paper/Photo on Photo Paper: "
+ *MediaType Glossy
+ *ColorModel RGB
+ *Resolution 300dpi
+ com.apple.print.preset.graphicsType Photo
+ com.apple.print.preset.quality mid
+ com.apple.print.preset.media-front-coating glossy"
+*End
+*fr.APPrinterPreset Photo_on_Photo_Paper/Photo sur papier photographique: ""
+
+
+
+
+
*APPrinterPrinterUtilityPath: "/Library/Printers/vendor/filename.app"
+
+
This keyword defines a GUI application that can be used to do printer
+maintenance functions such as cleaning the print head(s). See ... for more
+information.
+
+
Examples:
+
+
+*% Define the printer utility application
+*APPrinterPrinterUtilityPath: "/Library/Printers/vendor/Tools/utility.app"
+
+
+
+
+
*APScannerOnly: boolean
+
+
This keyword specifies whether the device has scanning but no printing
+capabilities. The default is False.
+
+
Examples:
+
+
+*APICADriver: True
+*APScannerOnly: True
+
+
+
+
+
*APScanAppBundleID: "bundle ID"
+
+
This keyword defines the application to use when scanning pages from
+the device.
+
+
Examples:
+
+
+*APICADriver: True
+*APScanAppBundleID: "com.apple.ImageCaptureApp"
+
+
+
+
+
+
Changes in CUPS 1.5
+
+
+
+ - Changes all instances of PPD attributes to PPD keywords, to be consistent with the parent specification from Adobe.
+
+
+
+
+
Changes in CUPS 1.4.5
+
+
+
+
+
Changes in CUPS 1.4
+
+
+
+
+
Changes in CUPS 1.3.1
+
+
+
+ - Added missing Mac OS X AP keywords.
+
+ - Added section on auto-configuration including the
+ OIDMainKeyword and ?MainKeyword
+ keywords.
+
+ - Minor reorganization.
+
+
+
+
+
Changes in CUPS 1.3
+
+
+
+
Changes in CUPS 1.2.8
+
+
+
+ - Added section on supported PostScript commands for raster
+ drivers
+
+
+
+
Changes in CUPS 1.2
+
+
+
+
Changes in CUPS 1.1
+
+
diff --git a/man/cupsd.conf.man.in b/man/cupsd.conf.man.in
index ad4d082b3..d32412110 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" "28 January 2010" "Apple Inc."
+.TH cupsd.conf 5 "CUPS" "5 November 2010" "Apple Inc."
.SH NAME
cupsd.conf \- server configuration file for cups
.SH DESCRIPTION
@@ -400,6 +400,26 @@ JobKillDelay seconds
Specifies the number of seconds to wait before killing the filters and backend
associated with a canceled or held job.
.TP 5
+JobPrivateAccess all
+.TP 5
+JobPrivateAccess default
+.TP 5
+JobPrivateAccess {user|@group|@ACL|@OWNER|@SYSTEM}+
+.br
+Specifies an access list for a job's private values. The "default" access list
+is "@OWNER @SYSTEM". "@ACL" maps to the printer's requesting-user-name-allowed
+or requesting-user-name-denied values.
+.TP 5
+JobPrivateValues all
+.TP 5
+JobPrivateValues default
+.TP 5
+JobPrivateValues none
+.TP 5
+JobPrivateValues attribute-name-1 [ ... attribute-name-N ]
+Specifies the list of job values to make private. The "default" values are
+"job-name", "job-originating-host-name", and "job-originating-user-name".
+.TP 5
JobRetryInterval seconds
.br
Specifies the interval between retries of jobs in seconds.
@@ -686,6 +706,27 @@ SSLPort
.br
Listens on the specified port for encrypted connections.
.TP 5
+SubscriptionPrivateAccess all
+.TP 5
+SubscriptionPrivateAccess default
+.TP 5
+SubscriptionPrivateAccess {user|@group|@ACL|@OWNER|@SYSTEM}+
+.br
+Specifies an access list for a subscription's private values. The "default"
+access list is "@OWNER @SYSTEM". "@ACL" maps to the printer's
+requesting-user-name-allowed or requesting-user-name-denied values.
+.TP 5
+SubscriptionPrivateValues all
+.TP 5
+SubscriptionPrivateValues default
+.TP 5
+SubscriptionPrivateValues none
+.TP 5
+SubscriptionPrivateValues attribute-name-1 [ ... attribute-name-N ]
+Specifies the list of job values to make private. The "default" values are
+"notify-events", "notify-pull-method", "notify-recipient-uri",
+"notify-subscriber-user-name", and "notify-user-data".
+.TP 5
SystemGroup group-name [group-name ...]
.br
Specifies the group(s) to use for System class authentication.
@@ -708,7 +749,7 @@ Specifies the user name or ID that is used when running external programs.
.br
http://localhost:631/help
.SH COPYRIGHT
-Copyright 2007-2009 by Apple Inc.
+Copyright 2007-2010 by Apple Inc.
.\"
.\" End of "$Id: cupsd.conf.man.in 7935 2008-09-11 01:54:11Z mike $".
.\"
diff --git a/man/ipptool.man b/man/ipptool.man
index 1e9f59b3c..31bd93de6 100644
--- a/man/ipptool.man
+++ b/man/ipptool.man
@@ -11,12 +11,14 @@
.\" 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 ipptool 1 "CUPS" "2 August 2010" "Apple Inc."
+.TH ipptool 1 "CUPS" "17 October 2010" "Apple Inc."
.SH NAME
ipptool - perform internet printing protocol requests
.SH SYNOPSIS
.B ipptool
-[ -C ] [ -E ] [ -I ] [ -L ] [ -S ] [ -V
+[ -C ] [ -E ] [ -I ] [ -L ] [ -S ] [ -T
+.I seconds
+] [ -V
.I version
] [ -X ] [ -c ] [ -d
.I name=value
@@ -52,6 +54,9 @@ Specifies that requests should be sent using the HTTP/1.0 "Content-Length:" head
-S
Forces (dedicated) SSL encryption when connecting to the server.
.TP 5
+-T seconds
+Specifies a timeout for IPP requests in seconds.
+.TP 5
-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.
.TP 5
@@ -68,7 +73,7 @@ Defines the named variable.
Defines the default request filename for tests.
.TP 5
-i seconds
-Specifies that the (last) file should be repeated at the specified interval. This option is incompatible with the \fI-x\fR (XML plist output) option.
+Specifies that the (last) file should be repeated at the specified interval. This option is incompatible with the \fI-X\fR (XML plist output) option.
.TP 5
-l
Specifies that plain text output is desired.
diff --git a/scheduler/auth.c b/scheduler/auth.c
index 497997d6f..8b3571f29 100644
--- a/scheduler/auth.c
+++ b/scheduler/auth.c
@@ -1,9 +1,9 @@
/*
* "$Id: auth.c 7830 2008-08-04 20:38:50Z mike $"
*
- * Authorization routines for the Common UNIX Printing System (CUPS).
+ * Authorization routines for the CUPS scheduler.
*
- * Copyright 2007-2009 by Apple Inc.
+ * Copyright 2007-2010 by Apple Inc.
* Copyright 1997-2007 by Easy Software Products, all rights reserved.
*
* This file contains Kerberos support code, copyright 2006 by
@@ -17,12 +17,11 @@
*
* Contents:
*
+ * cupsdAddIPMask() - Add an IP address authorization mask.
* cupsdAddLocation() - Add a location for authorization.
* cupsdAddName() - Add a name to a location...
- * cupsdAllowHost() - Add a host name that is allowed to access the
- * location.
- * cupsdAllowIP() - Add an IP address or network that is allowed to
- * access the location.
+ * cupsdAddNameMask() - Add a host or interface name authorization
+ * mask.
* cupsdAuthorize() - Validate any authorization credentials.
* cupsdCheckAccess() - Check whether the given address is allowed to
* access a location.
@@ -32,22 +31,19 @@
* cupsdCopyLocation() - Make a copy of a location...
* cupsdDeleteAllLocations() - Free all memory used for location
* authorization.
- * cupsdDeleteLocation() - Free all memory used by a location.
- * cupsdDenyHost() - Add a host name that is not allowed to access
- * the location.
- * cupsdDenyIP() - Add an IP address or network that is not
- * allowed to access the location.
* cupsdFindBest() - Find the location entry that best matches the
* resource.
* cupsdFindLocation() - Find the named location.
+ * cupsdFreeLocation() - Free all memory used by a location.
* cupsdIsAuthorized() - Check to see if the user is authorized...
- * add_allow() - Add an allow mask to the location.
- * add_deny() - Add a deny mask to the location.
+ * cupsdNewLocation() - Create a new location for authorization.
* check_authref() - Check if an authorization services reference
* has the supplied right.
* compare_locations() - Compare two locations.
+ * copy_authmask() - Copy function for auth masks.
* cups_crypt() - Encrypt the password using the DES or MD5
* algorithms, as needed.
+ * free_authmask() - Free function for auth masks.
* get_md5_password() - Get an MD5 password.
* pam_func() - PAM conversation function.
* to64() - Base64-encode an integer value...
@@ -108,16 +104,16 @@ extern void krb5_ipc_client_clear_target(void);
* Local functions...
*/
-static cupsd_authmask_t *add_allow(cupsd_location_t *loc);
-static cupsd_authmask_t *add_deny(cupsd_location_t *loc);
#ifdef HAVE_AUTHORIZATION_H
static int check_authref(cupsd_client_t *con, const char *right);
#endif /* HAVE_AUTHORIZATION_H */
static int compare_locations(cupsd_location_t *a,
cupsd_location_t *b);
+static cupsd_authmask_t *copy_authmask(cupsd_authmask_t *am, void *data);
#if !HAVE_LIBPAM && !defined(HAVE_USERSEC_H)
static char *cups_crypt(const char *pw, const char *salt);
#endif /* !HAVE_LIBPAM && !HAVE_USERSEC_H */
+static void free_authmask(cupsd_authmask_t *am, void *data);
static char *get_md5_password(const char *username,
const char *group, char passwd[33]);
#if HAVE_LIBPAM
@@ -151,54 +147,66 @@ static cupsd_authdata_t *auth_data; /* Current client being authenticated */
/*
- * 'cupsdAddLocation()' - Add a location for authorization.
+ * 'cupsdAddIPMask()' - Add an IP address authorization mask.
*/
-cupsd_location_t * /* O - Pointer to new location record */
-cupsdAddLocation(const char *location) /* I - Location path */
+int /* O - 1 on success, 0 on failure */
+cupsdAddIPMask(
+ cups_array_t **masks, /* IO - Masks array (created as needed) */
+ const unsigned address[4], /* I - IP address */
+ const unsigned netmask[4]) /* I - IP netmask */
{
- cupsd_location_t *temp; /* New location */
+ cupsd_authmask_t temp; /* New host/domain mask */
- /*
- * Make sure the locations array is created...
- */
-
- if (!Locations)
- Locations = cupsArrayNew((cups_array_func_t)compare_locations, NULL);
+ cupsdLogMessage(CUPSD_LOG_DEBUG2,
+ "cupsdAddIPMask(masks=%p(%p), address=%x:%x:%x:%x, "
+ "netmask=%x:%x:%x:%x)",
+ masks, *masks,
+ address[0], address[1], address[2], address[3],
+ netmask[0], netmask[1], netmask[2], netmask[3]);
- if (!Locations)
- return (NULL);
+ temp.type = CUPSD_AUTH_IP;
+ memcpy(temp.mask.ip.address, address, sizeof(temp.mask.ip.address));
+ memcpy(temp.mask.ip.netmask, netmask, sizeof(temp.mask.ip.netmask));
/*
- * Try to allocate memory for the new location.
+ * Create the masks array as needed and add...
*/
- if ((temp = calloc(1, sizeof(cupsd_location_t))) == NULL)
- return (NULL);
+ if (!*masks)
+ *masks = cupsArrayNew3(NULL, NULL, NULL, 0,
+ (cups_acopy_func_t)copy_authmask,
+ (cups_afree_func_t)free_authmask);
- /*
- * Initialize the record and copy the name over...
- */
-
- if ((temp->location = strdup(location)) == NULL)
- {
- free(temp);
- return (NULL);
- }
-
- temp->length = strlen(temp->location);
+ return (cupsArrayAdd(*masks, &temp));
+}
- cupsArrayAdd(Locations, temp);
- cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdAddLocation: added location \'%s\'",
- location);
+/*
+ * 'cupsdAddLocation()' - Add a location for authorization.
+ */
+void
+cupsdAddLocation(cupsd_location_t *loc) /* I - Location to add */
+{
/*
- * Return the new record...
+ * Make sure the locations array is created...
*/
- return (temp);
+ if (!Locations)
+ Locations = cupsArrayNew3((cups_array_func_t)compare_locations, NULL,
+ (cups_ahash_func_t)NULL, 0,
+ (cups_acopy_func_t)NULL,
+ (cups_afree_func_t)cupsdFreeLocation);
+
+ if (Locations)
+ {
+ cupsArrayAdd(Locations, loc);
+
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdAddLocation: Added location \"%s\"",
+ loc->location ? loc->location : "(null)");
+ }
}
@@ -210,126 +218,98 @@ void
cupsdAddName(cupsd_location_t *loc, /* I - Location to add to */
char *name) /* I - Name to add */
{
- char **temp; /* Pointer to names array */
-
-
cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdAddName(loc=%p, name=\"%s\")",
loc, name);
- if (loc->num_names == 0)
- temp = malloc(sizeof(char *));
- else
- temp = realloc(loc->names, (loc->num_names + 1) * sizeof(char *));
-
- if (temp == NULL)
- {
- cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to add name to location %s: %s",
- loc->location ? loc->location : "nil", strerror(errno));
- return;
- }
-
- loc->names = temp;
+ if (!loc->names)
+ loc->names = cupsArrayNew3(NULL, NULL, NULL, 0,
+ (cups_acopy_func_t)_cupsStrAlloc,
+ (cups_afree_func_t)_cupsStrFree);
- if ((temp[loc->num_names] = strdup(name)) == NULL)
+ if (!cupsArrayAdd(loc->names, name))
{
cupsdLogMessage(CUPSD_LOG_ERROR,
"Unable to duplicate name for location %s: %s",
loc->location ? loc->location : "nil", strerror(errno));
return;
}
-
- loc->num_names ++;
}
/*
- * 'cupsdAllowHost()' - Add a host name that is allowed to access the location.
+ * 'cupsdAddNameMask()' - Add a host or interface name authorization mask.
*/
-void
-cupsdAllowHost(cupsd_location_t *loc, /* I - Location to add to */
- char *name) /* I - Name of host or domain to add */
+int /* O - 1 on success, 0 on failure */
+cupsdAddNameMask(cups_array_t **masks, /* IO - Masks array (created as needed) */
+ char *name) /* I - Host or interface name */
{
- cupsd_authmask_t *temp; /* New host/domain mask */
+ cupsd_authmask_t temp; /* New host/domain mask */
char ifname[32], /* Interface name */
*ifptr; /* Pointer to end of name */
- cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdAllowHost(loc=%p(%s), name=\"%s\")",
- loc, loc->location ? loc->location : "nil", name);
-
- if ((temp = add_allow(loc)) == NULL)
- return;
+ cupsdLogMessage(CUPSD_LOG_DEBUG2,
+ "cupsdAddNameMask(masks=%p(%p), name=\"%s\")",
+ masks, *masks, name);
if (!strcasecmp(name, "@LOCAL"))
{
/*
- * Allow *interface*...
+ * Deny *interface*...
*/
- temp->type = CUPSD_AUTH_INTERFACE;
- temp->mask.name.name = strdup("*");
- temp->mask.name.length = 1;
+ temp.type = CUPSD_AUTH_INTERFACE;
+ temp.mask.name.name = (char *)"*";
}
else if (!strncasecmp(name, "@IF(", 4))
{
/*
- * Allow *interface*...
+ * Deny *interface*...
*/
strlcpy(ifname, name + 4, sizeof(ifname));
- ifptr = ifname + strlen(ifname);
+ ifptr = ifname + strlen(ifname) - 1;
- if (ifptr[-1] == ')')
+ if (ifptr >= ifname && *ifptr == ')')
{
ifptr --;
*ifptr = '\0';
}
- temp->type = CUPSD_AUTH_INTERFACE;
- temp->mask.name.name = strdup(ifname);
- temp->mask.name.length = ifptr - ifname;
+ temp.type = CUPSD_AUTH_INTERFACE;
+ temp.mask.name.name = ifname;
}
else
{
/*
- * Allow name...
+ * Deny name...
*/
- temp->type = CUPSD_AUTH_NAME;
- temp->mask.name.name = strdup(name);
- temp->mask.name.length = strlen(name);
- }
-}
-
+ if (*name == '*')
+ name ++;
-/*
- * 'cupsdAllowIP()' - Add an IP address or network that is allowed to access
- * the location.
- */
+ temp.type = CUPSD_AUTH_NAME;
+ temp.mask.name.name = (char *)name;
+ }
-void
-cupsdAllowIP(
- cupsd_location_t *loc, /* I - Location to add to */
- const unsigned address[4], /* I - IP address to add */
- const unsigned netmask[4]) /* I - Netmask of address */
-{
- cupsd_authmask_t *temp; /* New host/domain mask */
+ /*
+ * Set the name length...
+ */
+ temp.mask.name.length = strlen(temp.mask.name.name);
- cupsdLogMessage(CUPSD_LOG_DEBUG2,
- "cupsdAllowIP(loc=%p(%s), address=%x:%x:%x:%x, netmask=%x:%x:%x:%x)",
- loc, loc->location ? loc->location : "nil",
- address[0], address[1], address[2], address[3],
- netmask[0], netmask[1], netmask[2], netmask[3]);
+ /*
+ * Create the masks array as needed and add...
+ */
- if ((temp = add_allow(loc)) == NULL)
- return;
+ if (!*masks)
+ *masks = cupsArrayNew3(NULL, NULL, NULL, 0,
+ (cups_acopy_func_t)copy_authmask,
+ (cups_afree_func_t)free_authmask);
- temp->type = CUPSD_AUTH_IP;
- memcpy(temp->mask.ip.address, address, sizeof(temp->mask.ip.address));
- memcpy(temp->mask.ip.netmask, netmask, sizeof(temp->mask.ip.netmask));
+ return (cupsArrayAdd(*masks, &temp));
}
@@ -1232,20 +1212,20 @@ cupsdCheckAccess(
case CUPSD_AUTH_ALLOW : /* Order Deny,Allow */
allow = 1;
- if (cupsdCheckAuth(ip, name, namelen, loc->num_deny, loc->deny))
+ if (cupsdCheckAuth(ip, name, namelen, loc->deny))
allow = 0;
- if (cupsdCheckAuth(ip, name, namelen, loc->num_allow, loc->allow))
+ if (cupsdCheckAuth(ip, name, namelen, loc->allow))
allow = 1;
break;
case CUPSD_AUTH_DENY : /* Order Allow,Deny */
allow = 0;
- if (cupsdCheckAuth(ip, name, namelen, loc->num_allow, loc->allow))
+ if (cupsdCheckAuth(ip, name, namelen, loc->allow))
allow = 1;
- if (cupsdCheckAuth(ip, name, namelen, loc->num_deny, loc->deny))
+ if (cupsdCheckAuth(ip, name, namelen, loc->deny))
allow = 0;
break;
}
@@ -1260,24 +1240,25 @@ cupsdCheckAccess(
*/
int /* O - 1 if mask matches, 0 otherwise */
-cupsdCheckAuth(
- unsigned ip[4], /* I - Client address */
- char *name, /* I - Client hostname */
- int name_len, /* I - Length of hostname */
- int num_masks, /* I - Number of masks */
- cupsd_authmask_t *masks) /* I - Masks */
+cupsdCheckAuth(unsigned ip[4], /* I - Client address */
+ char *name, /* I - Client hostname */
+ int name_len, /* I - Length of hostname */
+ cups_array_t *masks) /* I - Masks */
{
- int i; /* Looping var */
- cupsd_netif_t *iface; /* Network interface */
- unsigned netip4; /* IPv4 network address */
+ int i; /* Looping var */
+ cupsd_authmask_t *mask; /* Current mask */
+ cupsd_netif_t *iface; /* Network interface */
+ unsigned netip4; /* IPv4 network address */
#ifdef AF_INET6
- unsigned netip6[4]; /* IPv6 network address */
+ unsigned netip6[4]; /* IPv6 network address */
#endif /* AF_INET6 */
- while (num_masks > 0)
+ for (mask = (cupsd_authmask_t *)cupsArrayFirst(masks);
+ mask;
+ mask = (cupsd_authmask_t *)cupsArrayNext(masks))
{
- switch (masks->type)
+ switch (mask->type)
{
case CUPSD_AUTH_INTERFACE :
/*
@@ -1293,7 +1274,7 @@ cupsdCheckAuth(
netip6[3] = htonl(ip[3]);
#endif /* AF_INET6 */
- if (!strcmp(masks->mask.name.name, "*"))
+ if (!strcmp(mask->mask.name.name, "*"))
{
#ifdef __APPLE__
/*
@@ -1361,7 +1342,7 @@ cupsdCheckAuth(
iface;
iface = (cupsd_netif_t *)cupsArrayNext(NetIFList))
{
- if (strcmp(masks->mask.name.name, iface->name))
+ if (strcmp(mask->mask.name.name, iface->name))
continue;
if (iface->address.addr.sa_family == AF_INET)
@@ -1401,17 +1382,17 @@ cupsdCheckAuth(
* Check for exact name match...
*/
- if (!strcasecmp(name, masks->mask.name.name))
+ if (!strcasecmp(name, mask->mask.name.name))
return (1);
/*
* Check for domain match...
*/
- if (name_len >= masks->mask.name.length &&
- masks->mask.name.name[0] == '.' &&
- !strcasecmp(name + name_len - masks->mask.name.length,
- masks->mask.name.name))
+ if (name_len >= mask->mask.name.length &&
+ mask->mask.name.name[0] == '.' &&
+ !strcasecmp(name + name_len - mask->mask.name.length,
+ mask->mask.name.name))
return (1);
break;
@@ -1421,17 +1402,14 @@ cupsdCheckAuth(
*/
for (i = 0; i < 4; i ++)
- if ((ip[i] & masks->mask.ip.netmask[i]) !=
- masks->mask.ip.address[i])
+ if ((ip[i] & mask->mask.ip.netmask[i]) !=
+ mask->mask.ip.address[i])
break;
if (i == 4)
return (1);
break;
}
-
- masks ++;
- num_masks --;
}
return (0);
@@ -1731,137 +1709,78 @@ cupsdCopyKrb5Creds(cupsd_client_t *con) /* I - Client connection */
cupsd_location_t * /* O - New location */
cupsdCopyLocation(
- cupsd_location_t **loc) /* IO - Original location */
+ cupsd_location_t *loc) /* I - Original location */
{
- int i; /* Looping var */
cupsd_location_t *temp; /* New location */
- char location[HTTP_MAX_URI];
- /* Location of resource */
/*
- * Use a local copy of location because cupsdAddLocation may cause
- * this memory to be moved...
+ * Make a copy of the original location...
*/
- strlcpy(location, (*loc)->location, sizeof(location));
-
- if ((temp = cupsdAddLocation(location)) == NULL)
+ if ((temp = calloc(1, sizeof(cupsd_location_t))) == NULL)
return (NULL);
/*
* Copy the information from the original location to the new one.
*/
- temp->limit = (*loc)->limit;
- temp->order_type = (*loc)->order_type;
- temp->type = (*loc)->type;
- temp->level = (*loc)->level;
- temp->satisfy = (*loc)->satisfy;
- temp->encryption = (*loc)->encryption;
+ if (!loc)
+ return (temp);
- if ((temp->num_names = (*loc)->num_names) > 0)
- {
- /*
- * Copy the names array...
- */
+ if (loc->location)
+ temp->location = _cupsStrAlloc(loc->location);
+
+ temp->limit = loc->limit;
+ temp->order_type = loc->order_type;
+ temp->type = loc->type;
+ temp->level = loc->level;
+ temp->satisfy = loc->satisfy;
+ temp->encryption = loc->encryption;
- if ((temp->names = calloc(temp->num_names, sizeof(char *))) == NULL)
+ if (loc->names)
+ {
+ if ((temp->names = cupsArrayDup(loc->names)) == NULL)
{
cupsdLogMessage(CUPSD_LOG_ERROR,
- "cupsdCopyLocation: Unable to allocate memory for %d names: %s",
- temp->num_names, strerror(errno));
+ "Unable to allocate memory for %d names: %s",
+ cupsArrayCount(loc->names), strerror(errno));
- cupsdDeleteLocation(temp);
+ cupsdFreeLocation(temp);
return (NULL);
}
-
- for (i = 0; i < temp->num_names; i ++)
- if ((temp->names[i] = strdup((*loc)->names[i])) == NULL)
- {
- cupsdLogMessage(CUPSD_LOG_ERROR,
- "cupsdCopyLocation: Unable to copy name \"%s\": %s",
- (*loc)->names[i], strerror(errno));
-
- cupsdDeleteLocation(temp);
- return (NULL);
- }
}
- if ((temp->num_allow = (*loc)->num_allow) > 0)
+ if (loc->allow)
{
/*
* Copy allow rules...
*/
- if ((temp->allow = calloc(temp->num_allow, sizeof(cupsd_authmask_t))) == NULL)
+ if ((temp->allow = cupsArrayDup(loc->allow)) == NULL)
{
cupsdLogMessage(CUPSD_LOG_ERROR,
- "cupsdCopyLocation: Unable to allocate memory for %d allow rules: %s",
- temp->num_allow, strerror(errno));
- cupsdDeleteLocation(temp);
+ "Unable to allocate memory for %d allow rules: %s",
+ cupsArrayCount(loc->allow), strerror(errno));
+ cupsdFreeLocation(temp);
return (NULL);
}
-
- for (i = 0; i < temp->num_allow; i ++)
- switch (temp->allow[i].type = (*loc)->allow[i].type)
- {
- case CUPSD_AUTH_NAME :
- temp->allow[i].mask.name.length = (*loc)->allow[i].mask.name.length;
- temp->allow[i].mask.name.name = strdup((*loc)->allow[i].mask.name.name);
-
- if (temp->allow[i].mask.name.name == NULL)
- {
- cupsdLogMessage(CUPSD_LOG_ERROR,
- "cupsdCopyLocation: Unable to copy allow name \"%s\": %s",
- (*loc)->allow[i].mask.name.name, strerror(errno));
- cupsdDeleteLocation(temp);
- return (NULL);
- }
- break;
- case CUPSD_AUTH_IP :
- memcpy(&(temp->allow[i].mask.ip), &((*loc)->allow[i].mask.ip),
- sizeof(cupsd_ipmask_t));
- break;
- }
}
- if ((temp->num_deny = (*loc)->num_deny) > 0)
+ if (loc->deny)
{
/*
* Copy deny rules...
*/
- if ((temp->deny = calloc(temp->num_deny, sizeof(cupsd_authmask_t))) == NULL)
+ if ((temp->deny = cupsArrayDup(loc->deny)) == NULL)
{
cupsdLogMessage(CUPSD_LOG_ERROR,
- "cupsdCopyLocation: Unable to allocate memory for %d deny rules: %s",
- temp->num_deny, strerror(errno));
- cupsdDeleteLocation(temp);
+ "Unable to allocate memory for %d deny rules: %s",
+ cupsArrayCount(loc->deny), strerror(errno));
+ cupsdFreeLocation(temp);
return (NULL);
}
-
- for (i = 0; i < temp->num_deny; i ++)
- switch (temp->deny[i].type = (*loc)->deny[i].type)
- {
- case CUPSD_AUTH_NAME :
- temp->deny[i].mask.name.length = (*loc)->deny[i].mask.name.length;
- temp->deny[i].mask.name.name = strdup((*loc)->deny[i].mask.name.name);
-
- if (temp->deny[i].mask.name.name == NULL)
- {
- cupsdLogMessage(CUPSD_LOG_ERROR,
- "cupsdCopyLocation: Unable to copy deny name \"%s\": %s",
- (*loc)->deny[i].mask.name.name, strerror(errno));
- cupsdDeleteLocation(temp);
- return (NULL);
- }
- break;
- case CUPSD_AUTH_IP :
- memcpy(&(temp->deny[i].mask.ip), &((*loc)->deny[i].mask.ip),
- sizeof(cupsd_ipmask_t));
- break;
- }
}
return (temp);
@@ -1875,20 +1794,8 @@ cupsdCopyLocation(
void
cupsdDeleteAllLocations(void)
{
- cupsd_location_t *loc; /* Current location */
-
-
/*
- * Free all of the allow/deny records first...
- */
-
- for (loc = (cupsd_location_t *)cupsArrayFirst(Locations);
- loc;
- loc = (cupsd_location_t *)cupsArrayNext(Locations))
- cupsdDeleteLocation(loc);
-
- /*
- * Then free the location array...
+ * Free the location array, which will free all of the locations...
*/
cupsArrayDelete(Locations);
@@ -1896,136 +1803,6 @@ cupsdDeleteAllLocations(void)
}
-/*
- * 'cupsdDeleteLocation()' - Free all memory used by a location.
- */
-
-void
-cupsdDeleteLocation(
- cupsd_location_t *loc) /* I - Location to delete */
-{
- int i; /* Looping var */
- cupsd_authmask_t *mask; /* Current mask */
-
-
- cupsArrayRemove(Locations, loc);
-
- for (i = loc->num_names - 1; i >= 0; i --)
- free(loc->names[i]);
-
- if (loc->num_names > 0)
- free(loc->names);
-
- for (i = loc->num_allow, mask = loc->allow; i > 0; i --, mask ++)
- if (mask->type == CUPSD_AUTH_NAME || mask->type == CUPSD_AUTH_INTERFACE)
- free(mask->mask.name.name);
-
- if (loc->num_allow > 0)
- free(loc->allow);
-
- for (i = loc->num_deny, mask = loc->deny; i > 0; i --, mask ++)
- if (mask->type == CUPSD_AUTH_NAME || mask->type == CUPSD_AUTH_INTERFACE)
- free(mask->mask.name.name);
-
- if (loc->num_deny > 0)
- free(loc->deny);
-
- free(loc->location);
- free(loc);
-}
-
-
-/*
- * 'cupsdDenyHost()' - Add a host name that is not allowed to access the
- * location.
- */
-
-void
-cupsdDenyHost(cupsd_location_t *loc, /* I - Location to add to */
- char *name) /* I - Name of host or domain to add */
-{
- cupsd_authmask_t *temp; /* New host/domain mask */
- char ifname[32], /* Interface name */
- *ifptr; /* Pointer to end of name */
-
-
- cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdDenyHost(loc=%p(%s), name=\"%s\")",
- loc, loc->location ? loc->location : "nil", name);
-
- if ((temp = add_deny(loc)) == NULL)
- return;
-
- if (!strcasecmp(name, "@LOCAL"))
- {
- /*
- * Deny *interface*...
- */
-
- temp->type = CUPSD_AUTH_INTERFACE;
- temp->mask.name.name = strdup("*");
- temp->mask.name.length = 1;
- }
- else if (!strncasecmp(name, "@IF(", 4))
- {
- /*
- * Deny *interface*...
- */
-
- strlcpy(ifname, name + 4, sizeof(ifname));
-
- ifptr = ifname + strlen(ifname);
-
- if (ifptr[-1] == ')')
- {
- ifptr --;
- *ifptr = '\0';
- }
-
- temp->type = CUPSD_AUTH_INTERFACE;
- temp->mask.name.name = strdup(ifname);
- temp->mask.name.length = ifptr - ifname;
- }
- else
- {
- /*
- * Deny name...
- */
-
- temp->type = CUPSD_AUTH_NAME;
- temp->mask.name.name = strdup(name);
- temp->mask.name.length = strlen(name);
- }
-}
-
-
-/*
- * 'cupsdDenyIP()' - Add an IP address or network that is not allowed to
- * access the location.
- */
-
-void
-cupsdDenyIP(cupsd_location_t *loc, /* I - Location to add to */
- const unsigned address[4],/* I - IP address to add */
- const unsigned netmask[4])/* I - Netmask of address */
-{
- cupsd_authmask_t *temp; /* New host/domain mask */
-
-
- cupsdLogMessage(CUPSD_LOG_DEBUG,
- "cupsdDenyIP(loc=%p(%s), address=%x:%x:%x:%x, netmask=%x:%x:%x:%x)",
- loc, loc->location ? loc->location : "nil",
- address[0], address[1], address[2], address[3],
- netmask[0], netmask[1], netmask[2], netmask[3]);
-
- if ((temp = add_deny(loc)) == NULL)
- return;
-
- temp->type = CUPSD_AUTH_IP;
- memcpy(temp->mask.ip.address, address, sizeof(temp->mask.ip.address));
- memcpy(temp->mask.ip.netmask, netmask, sizeof(temp->mask.ip.netmask));
-}
-
-
/*
* 'cupsdFindBest()' - Find the location entry that best matches the resource.
*/
@@ -2157,6 +1934,22 @@ cupsdFindLocation(const char *location) /* I - Connection */
}
+/*
+ * 'cupsdFreeLocation()' - Free all memory used by a location.
+ */
+
+void
+cupsdFreeLocation(cupsd_location_t *loc)/* I - Location to free */
+{
+ cupsArrayDelete(loc->names);
+ cupsArrayDelete(loc->allow);
+ cupsArrayDelete(loc->deny);
+
+ _cupsStrFree(loc->location);
+ free(loc);
+}
+
+
/*
* 'cupsdIsAuthorized()' - Check to see if the user is authorized...
*/
@@ -2165,13 +1958,14 @@ http_status_t /* O - HTTP_OK if authorized or error code */
cupsdIsAuthorized(cupsd_client_t *con, /* I - Connection */
const char *owner)/* I - Owner of object */
{
- int i, j, /* Looping vars */
+ int i, /* Looping vars */
auth, /* Authorization status */
type; /* Type of authentication */
unsigned address[4]; /* Authorization address */
cupsd_location_t *best; /* Best match for location so far */
int hostlen; /* Length of hostname */
- char username[256], /* Username to authorize */
+ char *name, /* Current username */
+ username[256], /* Username to authorize */
ownername[256], /* Owner name to authorize */
*ptr; /* Pointer into username */
struct passwd *pw; /* User password data */
@@ -2223,7 +2017,7 @@ cupsdIsAuthorized(cupsd_client_t *con, /* I - Connection */
"cupsdIsAuthorized: level=CUPSD_AUTH_%s, type=%s, "
"satisfy=CUPSD_AUTH_SATISFY_%s, num_names=%d",
levels[best->level], types[type],
- best->satisfy ? "ANY" : "ALL", best->num_names);
+ best->satisfy ? "ANY" : "ALL", cupsArrayCount(best->names));
if (best->limit == CUPSD_AUTH_LIMIT_IPP)
cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdIsAuthorized: op=%x(%s)",
@@ -2294,7 +2088,7 @@ cupsdIsAuthorized(cupsd_client_t *con, /* I - Connection */
*/
if (best->level == CUPSD_AUTH_ANON || /* Anonymous access - allow it */
- (type == CUPSD_AUTH_NONE && best->num_names == 0))
+ (type == CUPSD_AUTH_NONE && cupsArrayCount(best->names) == 0))
return (HTTP_OK);
if (!con->username[0] && type == CUPSD_AUTH_NONE &&
@@ -2393,7 +2187,7 @@ cupsdIsAuthorized(cupsd_client_t *con, /* I - Connection */
* any valid user is OK...
*/
- if (best->num_names == 0)
+ if (cupsArrayCount(best->names) == 0)
return (HTTP_OK);
/*
@@ -2411,13 +2205,13 @@ cupsdIsAuthorized(cupsd_client_t *con, /* I - Connection */
if (con->authref)
{
- for (i = 0; i < best->num_names; i ++)
+ for (name = (char *)cupsArrayFirst(best->names);
+ name;
+ name = (char *)cupsArrayNext(best->names))
{
- if (!strncasecmp(best->names[i], "@AUTHKEY(", 9) &&
- check_authref(con, best->names[i] + 9))
+ if (!strncasecmp(name, "@AUTHKEY(", 9) && check_authref(con, name + 9))
return (HTTP_OK);
- else if (!strcasecmp(best->names[i], "@SYSTEM") &&
- SystemGroupAuthKey &&
+ else if (!strcasecmp(name, "@SYSTEM") && SystemGroupAuthKey &&
check_authref(con, SystemGroupAuthKey))
return (HTTP_OK);
}
@@ -2426,23 +2220,25 @@ cupsdIsAuthorized(cupsd_client_t *con, /* I - Connection */
}
#endif /* HAVE_AUTHORIZATION_H */
- for (i = 0; i < best->num_names; i ++)
+ for (name = (char *)cupsArrayFirst(best->names);
+ name;
+ name = (char *)cupsArrayNext(best->names))
{
- if (!strcasecmp(best->names[i], "@OWNER") && owner &&
+ if (!strcasecmp(name, "@OWNER") && owner &&
!strcasecmp(username, ownername))
return (HTTP_OK);
- else if (!strcasecmp(best->names[i], "@SYSTEM"))
+ else if (!strcasecmp(name, "@SYSTEM"))
{
- for (j = 0; j < NumSystemGroups; j ++)
- if (cupsdCheckGroup(username, pw, SystemGroups[j]))
+ for (i = 0; i < NumSystemGroups; i ++)
+ if (cupsdCheckGroup(username, pw, SystemGroups[i]))
return (HTTP_OK);
}
- else if (best->names[i][0] == '@')
+ else if (name[0] == '@')
{
- if (cupsdCheckGroup(username, pw, best->names[i] + 1))
+ if (cupsdCheckGroup(username, pw, name + 1))
return (HTTP_OK);
}
- else if (!strcasecmp(username, best->names[i]))
+ else if (!strcasecmp(username, name))
return (HTTP_OK);
}
@@ -2460,19 +2256,21 @@ cupsdIsAuthorized(cupsd_client_t *con, /* I - Connection */
* Check to see if this user is in any of the named groups...
*/
- for (i = 0; i < best->num_names; i ++)
+ for (name = (char *)cupsArrayFirst(best->names);
+ name;
+ name = (char *)cupsArrayNext(best->names))
{
cupsdLogMessage(CUPSD_LOG_DEBUG2,
"cupsdIsAuthorized: Checking group \"%s\" membership...",
- best->names[i]);
+ name);
- if (!strcasecmp(best->names[i], "@SYSTEM"))
+ if (!strcasecmp(name, "@SYSTEM"))
{
- for (j = 0; j < NumSystemGroups; j ++)
- if (cupsdCheckGroup(username, pw, SystemGroups[j]))
+ for (i = 0; i < NumSystemGroups; i ++)
+ if (cupsdCheckGroup(username, pw, SystemGroups[i]))
return (HTTP_OK);
}
- else if (cupsdCheckGroup(username, pw, best->names[i]))
+ else if (cupsdCheckGroup(username, pw, name))
return (HTTP_OK);
}
@@ -2488,85 +2286,41 @@ cupsdIsAuthorized(cupsd_client_t *con, /* I - Connection */
/*
- * 'add_allow()' - Add an allow mask to the location.
- */
-
-static cupsd_authmask_t * /* O - New mask record */
-add_allow(cupsd_location_t *loc) /* I - Location to add to */
-{
- cupsd_authmask_t *temp; /* New mask record */
-
-
- /*
- * Range-check...
- */
-
- if (loc == NULL)
- return (NULL);
-
- /*
- * Try to allocate memory for the record...
- */
-
- if (loc->num_allow == 0)
- temp = malloc(sizeof(cupsd_authmask_t));
- else
- temp = realloc(loc->allow, sizeof(cupsd_authmask_t) * (loc->num_allow + 1));
-
- if (temp == NULL)
- return (NULL);
-
- loc->allow = temp;
- temp += loc->num_allow;
- loc->num_allow ++;
-
- /*
- * Clear the mask record and return...
- */
-
- memset(temp, 0, sizeof(cupsd_authmask_t));
- return (temp);
-}
-
-
-/*
- * 'add_deny()' - Add a deny mask to the location.
+ * 'cupsdNewLocation()' - Create a new location for authorization.
+ *
+ * Note: Still need to call cupsdAddLocation() to add it to the list of global
+ * locations.
*/
-static cupsd_authmask_t * /* O - New mask record */
-add_deny(cupsd_location_t *loc) /* I - Location to add to */
+cupsd_location_t * /* O - Pointer to new location record */
+cupsdNewLocation(const char *location) /* I - Location path */
{
- cupsd_authmask_t *temp; /* New mask record */
+ cupsd_location_t *temp; /* New location */
/*
- * Range-check...
+ * Try to allocate memory for the new location.
*/
- if (loc == NULL)
+ if ((temp = calloc(1, sizeof(cupsd_location_t))) == NULL)
return (NULL);
/*
- * Try to allocate memory for the record...
+ * Initialize the record and copy the name over...
*/
- if (loc->num_deny == 0)
- temp = malloc(sizeof(cupsd_authmask_t));
- else
- temp = realloc(loc->deny, sizeof(cupsd_authmask_t) * (loc->num_deny + 1));
-
- if (temp == NULL)
+ if ((temp->location = _cupsStrAlloc(location)) == NULL)
+ {
+ free(temp);
return (NULL);
+ }
- loc->deny = temp;
- temp += loc->num_deny;
- loc->num_deny ++;
+ temp->length = strlen(temp->location);
/*
- * Clear the mask record and return...
+ * Return the new record...
*/
- memset(temp, 0, sizeof(cupsd_authmask_t));
return (temp);
}
@@ -2636,6 +2390,45 @@ compare_locations(cupsd_location_t *a, /* I - First location */
}
+/*
+ * 'copy_authmask()' - Copy function for auth masks.
+ */
+
+static cupsd_authmask_t * /* O - New auth mask */
+copy_authmask(cupsd_authmask_t *mask, /* I - Existing auth mask */
+ void *data) /* I - User data (unused) */
+{
+ cupsd_authmask_t *temp; /* New auth mask */
+
+
+ (void)data;
+
+ if ((temp = malloc(sizeof(cupsd_authmask_t))) != NULL)
+ {
+ memcpy(temp, mask, sizeof(cupsd_authmask_t));
+
+ if (temp->type == CUPSD_AUTH_NAME || temp->type == CUPSD_AUTH_INTERFACE)
+ {
+ /*
+ * Make a copy of the name...
+ */
+
+ if ((temp->mask.name.name = _cupsStrAlloc(temp->mask.name.name)) == NULL)
+ {
+ /*
+ * Failed to make copy...
+ */
+
+ free(temp);
+ temp = NULL;
+ }
+ }
+ }
+
+ return (temp);
+}
+
+
#if !HAVE_LIBPAM && !defined(HAVE_USERSEC_H)
/*
* 'cups_crypt()' - Encrypt the password using the DES or MD5 algorithms,
@@ -2759,6 +2552,23 @@ cups_crypt(const char *pw, /* I - Password string */
#endif /* !HAVE_LIBPAM && !HAVE_USERSEC_H */
+/*
+ * 'free_authmask()' - Free function for auth masks.
+ */
+
+static void
+free_authmask(cupsd_authmask_t *mask, /* I - Auth mask to free */
+ void *data) /* I - User data (unused) */
+{
+ (void)data;
+
+ if (mask->type == CUPSD_AUTH_NAME || mask->type == CUPSD_AUTH_INTERFACE)
+ _cupsStrFree(mask->mask.name.name);
+
+ free(mask);
+}
+
+
/*
* 'get_md5_password()' - Get an MD5 password.
*/
diff --git a/scheduler/auth.h b/scheduler/auth.h
index 189ca2997..5e7525cbc 100644
--- a/scheduler/auth.h
+++ b/scheduler/auth.h
@@ -1,10 +1,9 @@
/*
* "$Id: auth.h 7317 2008-02-15 22:29:27Z mike $"
*
- * Authorization definitions for the Common UNIX Printing System (CUPS)
- * scheduler.
+ * Authorization definitions for the CUPS scheduler.
*
- * Copyright 2007-2009 by Apple Inc.
+ * Copyright 2007-2010 by Apple Inc.
* Copyright 1997-2006 by Easy Software Products, all rights reserved.
*
* These coded instructions, statements, and computer programs are the
@@ -98,12 +97,9 @@ typedef struct
type, /* Type of authentication */
level, /* Access level required */
satisfy; /* Satisfy any or all limits? */
- int num_names; /* Number of names */
- char **names; /* User or group names */
- int num_allow; /* Number of Allow lines */
- cupsd_authmask_t *allow; /* Allow lines */
- int num_deny; /* Number of Deny lines */
- cupsd_authmask_t *deny; /* Deny lines */
+ cups_array_t *names, /* User or group names */
+ *allow, /* Allow lines */
+ *deny; /* Deny lines */
http_encryption_t encryption; /* To encrypt or not to encrypt... */
} cupsd_location_t;
@@ -128,33 +124,30 @@ VAR http_encryption_t DefaultEncryption VALUE(HTTP_ENCRYPT_REQUIRED);
* Prototypes...
*/
-extern cupsd_location_t *cupsdAddLocation(const char *location);
+extern int cupsdAddIPMask(cups_array_t **masks,
+ const unsigned address[4],
+ const unsigned netmask[4]);
+extern void cupsdAddLocation(cupsd_location_t *loc);
extern void cupsdAddName(cupsd_location_t *loc, char *name);
-extern void cupsdAllowHost(cupsd_location_t *loc, char *name);
-extern void cupsdAllowIP(cupsd_location_t *loc,
- const unsigned address[4],
- const unsigned netmask[4]);
+extern int cupsdAddNameMask(cups_array_t **masks, char *name);
extern void cupsdAuthorize(cupsd_client_t *con);
extern int cupsdCheckAccess(unsigned ip[4], char *name,
int namelen, cupsd_location_t *loc);
extern int cupsdCheckAuth(unsigned ip[4], char *name, int namelen,
- int num_masks, cupsd_authmask_t *masks);
+ cups_array_t *masks);
extern int cupsdCheckGroup(const char *username,
struct passwd *user,
const char *groupname);
#ifdef HAVE_GSSAPI
extern krb5_ccache cupsdCopyKrb5Creds(cupsd_client_t *con);
#endif /* HAVE_GSSAPI */
-extern cupsd_location_t *cupsdCopyLocation(cupsd_location_t **loc);
+extern cupsd_location_t *cupsdCopyLocation(cupsd_location_t *loc);
extern void cupsdDeleteAllLocations(void);
-extern void cupsdDeleteLocation(cupsd_location_t *loc);
-extern void cupsdDenyHost(cupsd_location_t *loc, char *name);
-extern void cupsdDenyIP(cupsd_location_t *loc,
- const unsigned address[4],
- const unsigned netmask[4]);
extern cupsd_location_t *cupsdFindBest(const char *path, http_state_t state);
extern cupsd_location_t *cupsdFindLocation(const char *location);
+extern void cupsdFreeLocation(cupsd_location_t *loc);
extern http_status_t cupsdIsAuthorized(cupsd_client_t *con, const char *owner);
+extern cupsd_location_t *cupsdNewLocation(const char *location);
/*
diff --git a/scheduler/banners.c b/scheduler/banners.c
index ef73d2e7c..968de4911 100644
--- a/scheduler/banners.c
+++ b/scheduler/banners.c
@@ -1,9 +1,9 @@
/*
* "$Id: banners.c 7221 2008-01-16 22:20:08Z mike $"
*
- * Banner routines for the Common UNIX Printing System (CUPS).
+ * Banner routines for the CUPS scheduler.
*
- * Copyright 2007-2008 by Apple Inc.
+ * Copyright 2007-2010 by Apple Inc.
* Copyright 1997-2006 by Easy Software Products.
*
* These coded instructions, statements, and computer programs are the
diff --git a/scheduler/banners.h b/scheduler/banners.h
index 6ae8baa42..b215fe6ab 100644
--- a/scheduler/banners.h
+++ b/scheduler/banners.h
@@ -1,9 +1,9 @@
/*
* "$Id: banners.h 6649 2007-07-11 21:46:42Z mike $"
*
- * Banner definitions for the Common UNIX Printing System (CUPS).
+ * Banner definitions for the CUPS scheduler.
*
- * Copyright 2007 by Apple Inc.
+ * Copyright 2007-2010 by Apple Inc.
* Copyright 1997-2006 by Easy Software Products.
*
* These coded instructions, statements, and computer programs are the
diff --git a/scheduler/cert.c b/scheduler/cert.c
index c34efac0c..0e791f8c4 100644
--- a/scheduler/cert.c
+++ b/scheduler/cert.c
@@ -1,7 +1,7 @@
/*
* "$Id: cert.c 7673 2008-06-18 22:31:26Z mike $"
*
- * Authentication certificate routines for CUPS.
+ * Authentication certificate routines for the CUPS scheduler.
*
* Copyright 2007-2010 by Apple Inc.
* Copyright 1997-2006 by Easy Software Products.
diff --git a/scheduler/cert.h b/scheduler/cert.h
index 976600146..444897ebd 100644
--- a/scheduler/cert.h
+++ b/scheduler/cert.h
@@ -1,10 +1,9 @@
/*
* "$Id: cert.h 7383 2008-03-20 20:58:07Z mike $"
*
- * Authentication certificate definitions for the Common UNIX
- * Printing System (CUPS).
+ * Authentication certificate definitions for the CUPS scheduler.
*
- * Copyright 2007-2008 by Apple Inc.
+ * Copyright 2007-2010 by Apple Inc.
* Copyright 1997-2005 by Easy Software Products.
*
* These coded instructions, statements, and computer programs are the
diff --git a/scheduler/classes.c b/scheduler/classes.c
index 72b5dbff0..92122c068 100644
--- a/scheduler/classes.c
+++ b/scheduler/classes.c
@@ -1,7 +1,7 @@
/*
* "$Id: classes.c 7724 2008-07-14 06:06:06Z mike $"
*
- * Printer class routines for the Common UNIX Printing System (CUPS).
+ * Printer class routines for the CUPS scheduler.
*
* Copyright 2007-2010 by Apple Inc.
* Copyright 1997-2007 by Easy Software Products, all rights reserved.
@@ -584,7 +584,7 @@ cupsdLoadAllClasses(void)
if (value)
{
p->deny_users = 0;
- cupsdAddPrinterUser(p, value);
+ cupsdAddString(&(p->users), value);
}
else
cupsdLogMessage(CUPSD_LOG_ERROR,
@@ -595,7 +595,7 @@ cupsdLoadAllClasses(void)
if (value)
{
p->deny_users = 1;
- cupsdAddPrinterUser(p, value);
+ cupsdAddString(&(p->users), value);
}
else
cupsdLogMessage(CUPSD_LOG_ERROR,
@@ -685,7 +685,8 @@ cupsdSaveAllClasses(void)
cups_file_t *fp; /* classes.conf file */
char temp[1024], /* Temporary string */
backup[1024], /* printers.conf.O file */
- value[2048]; /* Value string */
+ value[2048], /* Value string */
+ *name; /* Current user name */
cupsd_printer_t *pclass; /* Current printer class */
int i; /* Looping var */
time_t curtime; /* Current time */
@@ -825,9 +826,10 @@ cupsdSaveAllClasses(void)
cupsFilePrintf(fp, "PageLimit %d\n", pclass->page_limit);
cupsFilePrintf(fp, "KLimit %d\n", pclass->k_limit);
- for (i = 0; i < pclass->num_users; i ++)
- cupsFilePutConf(fp, pclass->deny_users ? "DenyUser" : "AllowUser",
- pclass->users[i]);
+ for (name = (char *)cupsArrayFirst(pclass->users);
+ name;
+ name = (char *)cupsArrayNext(pclass->users))
+ cupsFilePutConf(fp, pclass->deny_users ? "DenyUser" : "AllowUser", name);
if (pclass->op_policy)
cupsFilePutConf(fp, "OpPolicy", pclass->op_policy);
diff --git a/scheduler/classes.h b/scheduler/classes.h
index e9940ce2b..ef415762a 100644
--- a/scheduler/classes.h
+++ b/scheduler/classes.h
@@ -1,7 +1,7 @@
/*
* "$Id: classes.h 6649 2007-07-11 21:46:42Z mike $"
*
- * Printer class definitions for the Common UNIX Printing System (CUPS).
+ * Printer class definitions for the CUPS scheduler.
*
* Copyright 2007-2010 by Apple Inc.
* Copyright 1997-2005 by Easy Software Products, all rights reserved.
diff --git a/scheduler/client.c b/scheduler/client.c
index 298fdfe30..f6a446195 100644
--- a/scheduler/client.c
+++ b/scheduler/client.c
@@ -1,7 +1,7 @@
/*
* "$Id: client.c 7950 2008-09-17 00:21:59Z mike $"
*
- * Client routines for the Common UNIX Printing System (CUPS) scheduler.
+ * Client routines for the CUPS scheduler.
*
* Copyright 2007-2010 by Apple Inc.
* Copyright 1997-2007 by Easy Software Products, all rights reserved.
@@ -2545,26 +2545,27 @@ cupsdSendHeader(
* parameter as needed...
*/
- int i; /* Looping var */
- char *auth_key; /* Auth key buffer */
+ char *name, /* Current user name */
+ *auth_key; /* Auth key buffer */
size_t auth_size; /* Size of remaining buffer */
auth_key = auth_str + strlen(auth_str);
auth_size = sizeof(auth_str) - (auth_key - auth_str);
- for (i = 0; i < con->best->num_names; i ++)
+ for (name = (char *)cupsArrayFirst(con->best->names);
+ name;
+ name = (char *)cupsArrayNext(con->best->names))
{
#ifdef HAVE_AUTHORIZATION_H
- if (!strncasecmp(con->best->names[i], "@AUTHKEY(", 9))
+ if (!strncasecmp(name, "@AUTHKEY(", 9))
{
- snprintf(auth_key, auth_size, ", authkey=\"%s\"",
- con->best->names[i] + 9);
+ snprintf(auth_key, auth_size, ", authkey=\"%s\"", name + 9);
/* end parenthesis is stripped in conf.c */
break;
}
else
#endif /* HAVE_AUTHORIZATION_H */
- if (!strcasecmp(con->best->names[i], "@SYSTEM"))
+ if (!strcasecmp(name, "@SYSTEM"))
{
#ifdef HAVE_AUTHORIZATION_H
if (SystemGroupAuthKey)
@@ -3513,7 +3514,19 @@ get_cdsa_certificate(
goto cleanup;
}
+ CFRelease(search);
+ search = NULL;
+ if ((err = SecIdentitySearchCreateWithPolicy(policy, NULL, CSSM_KEYUSE_SIGN,
+ keychain, FALSE, &search)))
+ {
+ cupsdLogMessage(CUPSD_LOG_ERROR,
+ "Cannot create identity search reference: %s (%d)",
+ cssmErrorString(err), (int)err);
+ goto cleanup;
+ }
+
err = SecIdentitySearchCopyNext(search, &identity);
+
}
if (err)
@@ -4477,11 +4490,21 @@ make_certificate(cupsd_client_t *con) /* I - Client connection */
*argv[4], /* Command-line arguments */
*envp[MAX_ENV + 1], /* Environment variables */
keychain[1024], /* Keychain argument */
- infofile[1024]; /* Type-in information for cert */
+ infofile[1024], /* Type-in information for cert */
+ localname[1024], /* Local hostname */
+ *servername; /* Name of server in cert */
cups_file_t *fp; /* Seed/info file */
int infofd; /* Info file descriptor */
+ if (con->servername && isdigit(con->servername[0] & 255) && DNSSDHostName)
+ {
+ snprintf(localname, sizeof(localname), "%s.local", DNSSDHostName);
+ servername = localname;
+ }
+ else
+ servername = con->servername;
+
/*
* Run the "certtool" command to generate a self-signed certificate...
*/
@@ -4509,7 +4532,7 @@ make_certificate(cupsd_client_t *con) /* I - Client connection */
}
cupsFilePrintf(fp, "%s\nr\n\ny\nb\ns\ny\n%s\n\n\n\n\n%s\ny\n",
- con->servername, con->servername, ServerAdmin);
+ servername, servername, ServerAdmin);
cupsFileClose(fp);
cupsdLogMessage(CUPSD_LOG_INFO,
diff --git a/scheduler/client.h b/scheduler/client.h
index aa2cee818..a88f9dcef 100644
--- a/scheduler/client.h
+++ b/scheduler/client.h
@@ -1,9 +1,9 @@
/*
* "$Id: client.h 7935 2008-09-11 01:54:11Z mike $"
*
- * Client definitions for the Common UNIX Printing System (CUPS) scheduler.
+ * Client definitions for the CUPS scheduler.
*
- * Copyright 2007-2009 by Apple Inc.
+ * Copyright 2007-2010 by Apple Inc.
* Copyright 1997-2007 by Easy Software Products, all rights reserved.
*
* These coded instructions, statements, and computer programs are the
diff --git a/scheduler/conf.c b/scheduler/conf.c
index a10f1cdb3..b85c79ce6 100644
--- a/scheduler/conf.c
+++ b/scheduler/conf.c
@@ -1,7 +1,7 @@
/*
- * "$Id: conf.c 7952 2008-09-17 00:56:20Z mike $"
+ * "$Id: conf.c 9352 2010-11-06 04:55:26Z mike $"
*
- * Configuration routines for the Common UNIX Printing System (CUPS).
+ * Configuration routines for the CUPS scheduler.
*
* Copyright 2007-2010 by Apple Inc.
* Copyright 1997-2007 by Easy Software Products, all rights reserved.
@@ -29,6 +29,7 @@
* read_configuration() - Read a configuration file.
* read_location() - Read a
definition.
* read_policy() - Read a definition.
+ * set_policy_defaults() - Set default policy values as needed.
*/
/*
@@ -209,6 +210,7 @@ static int parse_protocols(const char *s);
static int read_configuration(cups_file_t *fp);
static int read_location(cups_file_t *fp, char *name, int linenum);
static int read_policy(cups_file_t *fp, char *name, int linenum);
+static void set_policy_defaults(cupsd_policy_t *pol);
/*
@@ -462,8 +464,7 @@ cupsdReadConfiguration(void)
if (NumRelays > 0)
{
for (i = 0; i < NumRelays; i ++)
- if (Relays[i].from.type == CUPSD_AUTH_NAME)
- free(Relays[i].from.mask.name.name);
+ cupsArrayDelete(Relays[i].from);
free(Relays);
@@ -1166,6 +1167,27 @@ cupsdReadConfiguration(void)
DefaultPolicyPtr = p = cupsdAddPolicy("default");
cupsdLogMessage(CUPSD_LOG_INFO, "");
+
+ cupsdLogMessage(CUPSD_LOG_INFO, "JobPrivateAccess default");
+ cupsdAddString(&(p->job_access), "@OWNER");
+ cupsdAddString(&(p->job_access), "@SYSTEM");
+
+ cupsdLogMessage(CUPSD_LOG_INFO, "JobPrivateValues default");
+ cupsdAddString(&(p->job_attrs), "job-name");
+ cupsdAddString(&(p->job_attrs), "job-originating-host-name");
+ cupsdAddString(&(p->job_attrs), "job-originating-user-name");
+
+ cupsdLogMessage(CUPSD_LOG_INFO, "SubscriptionPrivateAccess default");
+ cupsdAddString(&(p->sub_access), "@OWNER");
+ cupsdAddString(&(p->sub_access), "@SYSTEM");
+
+ cupsdLogMessage(CUPSD_LOG_INFO, "SubscriptionPrivateValues default");
+ cupsdAddString(&(p->job_attrs), "notify-events");
+ cupsdAddString(&(p->job_attrs), "notify-pull-method");
+ cupsdAddString(&(p->job_attrs), "notify-recipient-uri");
+ cupsdAddString(&(p->job_attrs), "notify-subscriber-user-name");
+ cupsdAddString(&(p->job_attrs), "notify-user-data");
+
cupsdLogMessage(CUPSD_LOG_INFO,
"");
cupsdLogMessage(CUPSD_LOG_INFO, "Order Deny,Allow");
@@ -1185,7 +1207,7 @@ cupsdReadConfiguration(void)
"Set-Job-Attributes Create-Job-Subscription "
"Renew-Subscription Cancel-Subscription "
"Get-Notifications Reprocess-Job Cancel-Current-Job "
- "Suspend-Current-Job Resume-Job Cancel-Jobs "
+ "Suspend-Current-Job Resume-Job "
"Cancel-My-Jobs Close-Job CUPS-Move-Job "
"CUPS-Authenticate-Job CUPS-Get-Document>");
cupsdLogMessage(CUPSD_LOG_INFO, "Order Deny,Allow");
@@ -1213,7 +1235,6 @@ cupsdReadConfiguration(void)
cupsdAddPolicyOp(p, po, IPP_CANCEL_CURRENT_JOB);
cupsdAddPolicyOp(p, po, IPP_SUSPEND_CURRENT_JOB);
cupsdAddPolicyOp(p, po, IPP_RESUME_JOB);
- cupsdAddPolicyOp(p, po, IPP_CANCEL_JOBS);
cupsdAddPolicyOp(p, po, IPP_CANCEL_MY_JOBS);
cupsdAddPolicyOp(p, po, IPP_CLOSE_JOB);
cupsdAddPolicyOp(p, po, CUPS_MOVE_JOB);
@@ -1229,7 +1250,7 @@ cupsdReadConfiguration(void)
"Hold-New-Jobs Release-Held-New-Jobs "
"Deactivate-Printer Activate-Printer Restart-Printer "
"Shutdown-Printer Startup-Printer Promote-Job "
- "Schedule-Job-After CUPS-Add-Printer "
+ "Schedule-Job-After Cancel-Jobs CUPS-Add-Printer "
"CUPS-Delete-Printer CUPS-Add-Class CUPS-Delete-Class "
"CUPS-Accept-Jobs CUPS-Reject-Jobs CUPS-Set-Default>");
cupsdLogMessage(CUPSD_LOG_INFO, "Order Deny,Allow");
@@ -1257,6 +1278,7 @@ cupsdReadConfiguration(void)
cupsdAddPolicyOp(p, po, IPP_STARTUP_PRINTER);
cupsdAddPolicyOp(p, po, IPP_PROMOTE_JOB);
cupsdAddPolicyOp(p, po, IPP_SCHEDULE_JOB_AFTER);
+ cupsdAddPolicyOp(p, po, IPP_CANCEL_JOBS);
cupsdAddPolicyOp(p, po, CUPS_ADD_PRINTER);
cupsdAddPolicyOp(p, po, CUPS_DELETE_PRINTER);
cupsdAddPolicyOp(p, po, CUPS_ADD_CLASS);
@@ -1888,9 +1910,9 @@ parse_aaa(cupsd_location_t *loc, /* I - Location */
*/
if (!strcasecmp(line, "Allow"))
- cupsdAllowIP(loc, zeros, zeros);
+ cupsdAddIPMask(&(loc->allow), zeros, zeros);
else
- cupsdDenyIP(loc, zeros, zeros);
+ cupsdAddIPMask(&(loc->deny), zeros, zeros);
}
else if (!strcasecmp(value, "none"))
{
@@ -1899,9 +1921,9 @@ parse_aaa(cupsd_location_t *loc, /* I - Location */
*/
if (!strcasecmp(line, "Allow"))
- cupsdAllowIP(loc, ones, zeros);
+ cupsdAddIPMask(&(loc->allow), ones, zeros);
else
- cupsdDenyIP(loc, ones, zeros);
+ cupsdAddIPMask(&(loc->deny), ones, zeros);
}
#ifdef AF_INET6
else if (value[0] == '*' || value[0] == '.' ||
@@ -1918,9 +1940,9 @@ parse_aaa(cupsd_location_t *loc, /* I - Location */
value ++;
if (!strcasecmp(line, "Allow"))
- cupsdAllowHost(loc, value);
+ cupsdAddNameMask(&(loc->allow), value);
else
- cupsdDenyHost(loc, value);
+ cupsdAddNameMask(&(loc->deny), value);
}
else
{
@@ -1936,9 +1958,9 @@ parse_aaa(cupsd_location_t *loc, /* I - Location */
}
if (!strcasecmp(line, "Allow"))
- cupsdAllowIP(loc, ip, mask);
+ cupsdAddIPMask(&(loc->allow), ip, mask);
else
- cupsdDenyIP(loc, ip, mask);
+ cupsdAddIPMask(&(loc->deny), ip, mask);
}
/*
@@ -2407,8 +2429,6 @@ read_configuration(cups_file_t *fp) /* I - File to read from */
/* Line from file */
temp[HTTP_MAX_BUFFER],
/* Temporary buffer for value */
- temp2[HTTP_MAX_BUFFER],
- /* Temporary buffer 2 for value */
*ptr, /* Pointer into line/temp */
*value, /* Pointer to value */
*valueptr; /* Pointer into value */
@@ -2704,7 +2724,8 @@ read_configuration(cups_file_t *fp) /* I - File to read from */
*/
if ((location = cupsdFindLocation("CUPS_INTERNAL_BROWSE_ACL")) == NULL)
- location = cupsdAddLocation("CUPS_INTERNAL_BROWSE_ACL");
+ if ((location = cupsdNewLocation("CUPS_INTERNAL_BROWSE_ACL")) != NULL)
+ cupsdAddLocation(location);
if (location == NULL)
cupsdLogMessage(CUPSD_LOG_ERROR,
@@ -2752,35 +2773,43 @@ read_configuration(cups_file_t *fp) /* I - File to read from */
*/
if ((location = cupsdFindLocation("CUPS_INTERNAL_BROWSE_ACL")) == NULL)
- location = cupsdAddLocation("CUPS_INTERNAL_BROWSE_ACL");
+ 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
{
- while (*value)
+ if (!strncasecmp(value, "from", 4))
{
- if (!strncasecmp(value, "from", 4))
- {
- /*
- * Strip leading "from"...
- */
+ /*
+ * Skip leading "from"...
+ */
- value += 4;
+ value += 4;
+ }
- while (isspace(*value & 255))
- value ++;
+ while (*value)
+ {
+ /*
+ * Skip leading whitespace...
+ */
- if (!*value)
- break;
- }
+ while (isspace(*value & 255))
+ value ++;
+
+ if (!*value)
+ break;
/*
* Find the end of the value...
*/
- for (valueptr = value; *valueptr && !isspace(*valueptr & 255); valueptr ++);
+ for (valueptr = value;
+ *valueptr && !isspace(*valueptr & 255);
+ valueptr ++);
while (isspace(*valueptr & 255))
*valueptr++ = '\0';
@@ -2808,9 +2837,9 @@ read_configuration(cups_file_t *fp) /* I - File to read from */
*/
if (!strcasecmp(line, "BrowseAllow"))
- cupsdAllowIP(location, zeros, zeros);
+ cupsdAddIPMask(&(location->allow), zeros, zeros);
else
- cupsdDenyIP(location, zeros, zeros);
+ cupsdAddIPMask(&(location->deny), zeros, zeros);
}
else if (!strcasecmp(value, "none"))
{
@@ -2819,28 +2848,26 @@ read_configuration(cups_file_t *fp) /* I - File to read from */
*/
if (!strcasecmp(line, "BrowseAllow"))
- cupsdAllowIP(location, ones, zeros);
+ cupsdAddIPMask(&(location->allow), ones, zeros);
else
- cupsdDenyIP(location, ones, zeros);
+ 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))
+ else if (value[0] == '*' || value[0] == '.' ||
+ !isdigit(value[0] & 255))
#endif /* AF_INET6 */
{
/*
* Host or domain name...
*/
- if (value[0] == '*')
- value ++;
-
if (!strcasecmp(line, "BrowseAllow"))
- cupsdAllowHost(location, value);
+ cupsdAddNameMask(&(location->allow), value);
else
- cupsdDenyHost(location, value);
+ cupsdAddNameMask(&(location->deny), value);
}
else
{
@@ -2856,9 +2883,9 @@ read_configuration(cups_file_t *fp) /* I - File to read from */
}
if (!strcasecmp(line, "BrowseAllow"))
- cupsdAllowIP(location, ip, mask);
+ cupsdAddIPMask(&(location->allow), ip, mask);
else
- cupsdDenyIP(location, ip, mask);
+ cupsdAddIPMask(&(location->deny), ip, mask);
}
/*
@@ -2896,15 +2923,30 @@ read_configuration(cups_file_t *fp) /* I - File to read from */
if (!strncasecmp(value, "from ", 5))
{
/*
- * Strip leading "from"...
+ * Skip leading "from"...
*/
value += 5;
+ /*
+ * Skip leading whitespace...
+ */
+
while (isspace(*value))
value ++;
}
+ /*
+ * Find the end of the from value...
+ */
+
+ for (valueptr = value;
+ *valueptr && !isspace(*valueptr & 255);
+ valueptr ++);
+
+ while (isspace(*valueptr & 255))
+ *valueptr++ = '\0';
+
/*
* Figure out what form the from address takes:
*
@@ -2930,24 +2972,13 @@ read_configuration(cups_file_t *fp) /* I - File to read from */
* Host or domain name...
*/
- if (value[0] == '*')
- value ++;
-
- strlcpy(temp, value, sizeof(temp));
- if ((ptr = strchr(temp, ' ')) != NULL)
- *ptr = '\0';
-
- relay->from.type = CUPSD_AUTH_NAME;
-
- if ((relay->from.mask.name.name = strdup(temp)) == NULL)
+ if (!cupsdAddNameMask(&(relay->from), value))
{
cupsdLogMessage(CUPSD_LOG_ERROR,
"Unable to allocate BrowseRelay name at line %d - %s.",
linenum, strerror(errno));
continue;
}
-
- relay->from.mask.name.length = strlen(temp);
}
else
{
@@ -2962,41 +2993,32 @@ read_configuration(cups_file_t *fp) /* I - File to read from */
break;
}
- relay->from.type = CUPSD_AUTH_IP;
- memcpy(relay->from.mask.ip.address, ip,
- sizeof(relay->from.mask.ip.address));
- memcpy(relay->from.mask.ip.netmask, mask,
- sizeof(relay->from.mask.ip.netmask));
+ if (!cupsdAddIPMask(&(relay->from), ip, mask))
+ {
+ cupsdLogMessage(CUPSD_LOG_ERROR,
+ "Unable to allocate BrowseRelay IP at line %d - %s.",
+ linenum, strerror(errno));
+ continue;
+ }
}
/*
- * Skip value and trailing whitespace...
+ * Get "to" address and port...
*/
- for (; *value; value ++)
- if (isspace(*value))
- break;
-
- while (isspace(*value))
- value ++;
-
- if (!strncasecmp(value, "to ", 3))
+ if (!strncasecmp(valueptr, "to ", 3))
{
/*
* Strip leading "to"...
*/
- value += 3;
+ valueptr += 3;
- while (isspace(*value))
- value ++;
+ while (isspace(*valueptr))
+ valueptr ++;
}
- /*
- * Get "to" address and port...
- */
-
- if ((addrlist = get_address(value, BrowsePort)) != NULL)
+ if ((addrlist = get_address(valueptr, BrowsePort)) != NULL)
{
/*
* Only IPv4 addresses are supported...
@@ -3012,37 +3034,29 @@ read_configuration(cups_file_t *fp) /* I - File to read from */
httpAddrString(&(relay->to), temp, sizeof(temp));
- if (relay->from.type == CUPSD_AUTH_IP)
- snprintf(temp2, sizeof(temp2), "%u.%u.%u.%u/%u.%u.%u.%u",
- relay->from.mask.ip.address[0] >> 24,
- (relay->from.mask.ip.address[0] >> 16) & 255,
- (relay->from.mask.ip.address[0] >> 8) & 255,
- relay->from.mask.ip.address[0] & 255,
- relay->from.mask.ip.netmask[0] >> 24,
- (relay->from.mask.ip.netmask[0] >> 16) & 255,
- (relay->from.mask.ip.netmask[0] >> 8) & 255,
- relay->from.mask.ip.netmask[0] & 255);
- else
- strlcpy(temp2, relay->from.mask.name.name, sizeof(temp2));
-
cupsdLogMessage(CUPSD_LOG_INFO, "Relaying from %s to %s:%d (IPv4)",
- temp2, temp, ntohs(relay->to.ipv4.sin_port));
+ value, temp, ntohs(relay->to.ipv4.sin_port));
NumRelays ++;
}
else
+ {
+ cupsArrayDelete(relay->from);
+ relay->from = NULL;
+
cupsdLogMessage(CUPSD_LOG_ERROR, "Bad relay address %s at line %d.",
- value, linenum);
+ valueptr, linenum);
+ }
httpAddrFreeList(addrlist);
}
else
{
- if (relay->from.type == CUPSD_AUTH_NAME)
- free(relay->from.mask.name.name);
+ cupsArrayDelete(relay->from);
+ relay->from = NULL;
cupsdLogMessage(CUPSD_LOG_ERROR, "Bad relay address %s at line %d.",
- value, linenum);
+ valueptr, linenum);
}
}
else if (!strcasecmp(line, "BrowsePoll") && value)
@@ -3563,9 +3577,11 @@ read_location(cups_file_t *fp, /* I - Configuration file */
*valptr; /* Pointer into value */
- if ((parent = cupsdAddLocation(location)) == NULL)
+ if ((parent = cupsdNewLocation(location)) == NULL)
return (0);
+ cupsdAddLocation(parent);
+
parent->limit = CUPSD_AUTH_LIMIT_ALL;
loc = parent;
@@ -3589,9 +3605,11 @@ read_location(cups_file_t *fp, /* I - Configuration file */
continue;
}
- if ((loc = cupsdCopyLocation(&parent)) == NULL)
+ if ((loc = cupsdCopyLocation(parent)) == NULL)
return (0);
+ cupsdAddLocation(loc);
+
loc->limit = 0;
while (*value)
{
@@ -3694,106 +3712,7 @@ read_policy(cups_file_t *fp, /* I - Configuration file */
"Missing before on line %d!",
linenum);
- /*
- * Verify that we have an explicit policy for Validate-Job, Cancel-Jobs,
- * Cancel-My-Jobs, Close-Job, and CUPS-Get-Document, which ensures that
- * upgrades do not introduce new security issues...
- */
-
- if ((op = cupsdFindPolicyOp(pol, IPP_VALIDATE_JOB)) == NULL ||
- op->op == IPP_ANY_OPERATION)
- {
- if ((op = cupsdFindPolicyOp(pol, IPP_PRINT_JOB)) != NULL &&
- op->op != IPP_ANY_OPERATION)
- {
- /*
- * Add a new limit for Validate-Job using the Print-Job limit as a
- * template...
- */
-
- cupsdLogMessage(CUPSD_LOG_WARN,
- "No limit for Validate-Job defined in policy %s "
- "- using Print-Job's policy", pol->name);
-
- cupsdAddPolicyOp(pol, op, IPP_VALIDATE_JOB);
- }
- }
-
- if ((op = cupsdFindPolicyOp(pol, IPP_CANCEL_JOBS)) == NULL ||
- op->op == IPP_ANY_OPERATION)
- {
- if ((op = cupsdFindPolicyOp(pol, IPP_CANCEL_JOB)) != NULL &&
- op->op != IPP_ANY_OPERATION)
- {
- /*
- * Add a new limit for Cancel-Jobs using the Cancel-Job limit as a
- * template...
- */
-
- cupsdLogMessage(CUPSD_LOG_WARN,
- "No limit for Cancel-Jobs defined in policy %s "
- "- using Cancel-Job's policy", pol->name);
-
- cupsdAddPolicyOp(pol, op, IPP_CANCEL_JOBS);
- }
- }
-
- if ((op = cupsdFindPolicyOp(pol, IPP_CANCEL_MY_JOBS)) == NULL ||
- op->op == IPP_ANY_OPERATION)
- {
- if ((op = cupsdFindPolicyOp(pol, IPP_SEND_DOCUMENT)) != NULL &&
- op->op != IPP_ANY_OPERATION)
- {
- /*
- * Add a new limit for Cancel-My-Jobs using the Send-Document limit as
- * a template...
- */
-
- cupsdLogMessage(CUPSD_LOG_WARN,
- "No limit for Cancel-My-Jobs defined in policy %s "
- "- using Send-Document's policy", pol->name);
-
- cupsdAddPolicyOp(pol, op, IPP_CANCEL_MY_JOBS);
- }
- }
-
- if ((op = cupsdFindPolicyOp(pol, IPP_CLOSE_JOB)) == NULL ||
- op->op == IPP_ANY_OPERATION)
- {
- if ((op = cupsdFindPolicyOp(pol, IPP_SEND_DOCUMENT)) != NULL &&
- op->op != IPP_ANY_OPERATION)
- {
- /*
- * Add a new limit for Close-Job using the Send-Document limit as a
- * template...
- */
-
- cupsdLogMessage(CUPSD_LOG_WARN,
- "No limit for Close-Job defined in policy %s "
- "- using Send-Document's policy", pol->name);
-
- cupsdAddPolicyOp(pol, op, IPP_CLOSE_JOB);
- }
- }
-
- if ((op = cupsdFindPolicyOp(pol, CUPS_GET_DOCUMENT)) == NULL ||
- op->op == IPP_ANY_OPERATION)
- {
- if ((op = cupsdFindPolicyOp(pol, IPP_SEND_DOCUMENT)) != NULL &&
- op->op != IPP_ANY_OPERATION)
- {
- /*
- * Add a new limit for CUPS-Get-Document using the Send-Document
- * limit as a template...
- */
-
- cupsdLogMessage(CUPSD_LOG_WARN,
- "No limit for CUPS-Get-Document defined in policy %s "
- "- using Send-Document's policy", pol->name);
-
- cupsdAddPolicyOp(pol, op, CUPS_GET_DOCUMENT);
- }
- }
+ set_policy_defaults(pol);
return (linenum);
}
@@ -3874,6 +3793,109 @@ read_policy(cups_file_t *fp, /* I - Configuration file */
op = NULL;
}
+ else if (!strcasecmp(line, "JobPrivateAccess") ||
+ !strcasecmp(line, "JobPrivateValues") ||
+ !strcasecmp(line, "SubscriptionPrivateAccess") ||
+ !strcasecmp(line, "SubscriptionPrivateValues"))
+ {
+ if (op)
+ {
+ cupsdLogMessage(CUPSD_LOG_ERROR,
+ "%s directive must appear outside ... "
+ "on line %d.", line, linenum);
+ if (FatalErrors & CUPSD_FATAL_CONFIG)
+ return (0);
+ }
+ else
+ {
+ /*
+ * Pull out whitespace-delimited values...
+ */
+
+ while (*value)
+ {
+ /*
+ * Find the end of the current value...
+ */
+
+ for (valptr = value; !isspace(*valptr & 255) && *valptr; valptr ++);
+
+ if (*valptr)
+ *valptr++ = '\0';
+
+ /*
+ * Save it appropriately...
+ */
+
+ if (!strcasecmp(line, "JobPrivateAccess"))
+ {
+ /*
+ * JobPrivateAccess {all|default|user/group list|@@ACL}
+ */
+
+ if (!strcasecmp(value, "default"))
+ {
+ cupsdAddString(&(pol->job_access), "@OWNER");
+ cupsdAddString(&(pol->job_access), "@SYSTEM");
+ }
+ else
+ cupsdAddString(&(pol->job_access), value);
+ }
+ else if (!strcasecmp(line, "JobPrivateValues"))
+ {
+ /*
+ * JobPrivateValues {all|none|default|attribute list}
+ */
+
+ if (!strcasecmp(value, "default"))
+ {
+ cupsdAddString(&(pol->job_attrs), "job-name");
+ cupsdAddString(&(pol->job_attrs), "job-originating-host-name");
+ cupsdAddString(&(pol->job_attrs), "job-originating-user-name");
+ }
+ else
+ cupsdAddString(&(pol->job_attrs), value);
+ }
+ else if (!strcasecmp(line, "SubscriptionPrivateAccess"))
+ {
+ /*
+ * SubscriptionPrivateAccess {all|default|user/group list|@@ACL}
+ */
+
+ if (!strcasecmp(value, "default"))
+ {
+ cupsdAddString(&(pol->sub_access), "@OWNER");
+ cupsdAddString(&(pol->sub_access), "@SYSTEM");
+ }
+ else
+ cupsdAddString(&(pol->sub_access), value);
+ }
+ else /* if (!strcasecmp(line, "SubscriptionPrivateValues")) */
+ {
+ /*
+ * SubscriptionPrivateValues {all|none|default|attribute list}
+ */
+
+ if (!strcasecmp(value, "default"))
+ {
+ cupsdAddString(&(pol->sub_attrs), "notify-events");
+ cupsdAddString(&(pol->sub_attrs), "notify-pull-method");
+ cupsdAddString(&(pol->sub_attrs), "notify-recipient-uri");
+ cupsdAddString(&(pol->sub_attrs), "notify-subscriber-user-name");
+ cupsdAddString(&(pol->sub_attrs), "notify-user-data");
+ }
+ else
+ cupsdAddString(&(pol->sub_attrs), value);
+ }
+
+ /*
+ * Find the next string on the line...
+ */
+
+ for (value = valptr; isspace(*value & 255); value ++);
+ }
+ }
+ }
else if (!op)
{
cupsdLogMessage(CUPSD_LOG_ERROR,
@@ -3907,5 +3929,183 @@ read_policy(cups_file_t *fp, /* I - Configuration file */
/*
- * End of "$Id: conf.c 7952 2008-09-17 00:56:20Z mike $".
+ * 'set_policy_defaults()' - Set default policy values as needed.
+ */
+
+static void
+set_policy_defaults(cupsd_policy_t *pol)/* I - Policy */
+{
+ cupsd_location_t *op; /* Policy operation */
+
+
+ /*
+ * Verify that we have an explicit policy for Validate-Job, Cancel-Jobs,
+ * Cancel-My-Jobs, Close-Job, and CUPS-Get-Document, which ensures that
+ * upgrades do not introduce new security issues...
+ */
+
+ if ((op = cupsdFindPolicyOp(pol, IPP_VALIDATE_JOB)) == NULL ||
+ op->op == IPP_ANY_OPERATION)
+ {
+ if ((op = cupsdFindPolicyOp(pol, IPP_PRINT_JOB)) != NULL &&
+ op->op != IPP_ANY_OPERATION)
+ {
+ /*
+ * Add a new limit for Validate-Job using the Print-Job limit as a
+ * template...
+ */
+
+ cupsdLogMessage(CUPSD_LOG_WARN,
+ "No limit for Validate-Job defined in policy %s "
+ "- using Print-Job's policy.", pol->name);
+
+ cupsdAddPolicyOp(pol, op, IPP_VALIDATE_JOB);
+ }
+ else
+ cupsdLogMessage(CUPSD_LOG_WARN,
+ "No limit for Validate-Job defined in policy %s "
+ "and no suitable template found.", pol->name);
+ }
+
+ if ((op = cupsdFindPolicyOp(pol, IPP_CANCEL_JOBS)) == NULL ||
+ op->op == IPP_ANY_OPERATION)
+ {
+ if ((op = cupsdFindPolicyOp(pol, IPP_PAUSE_PRINTER)) != NULL &&
+ op->op != IPP_ANY_OPERATION)
+ {
+ /*
+ * Add a new limit for Cancel-Jobs using the Pause-Printer limit as a
+ * template...
+ */
+
+ cupsdLogMessage(CUPSD_LOG_WARN,
+ "No limit for Cancel-Jobs defined in policy %s "
+ "- using Pause-Printer's policy.", pol->name);
+
+ cupsdAddPolicyOp(pol, op, IPP_CANCEL_JOBS);
+ }
+ else
+ cupsdLogMessage(CUPSD_LOG_WARN,
+ "No limit for Cancel-Jobs defined in policy %s "
+ "and no suitable template found.", pol->name);
+ }
+
+ if ((op = cupsdFindPolicyOp(pol, IPP_CANCEL_MY_JOBS)) == NULL ||
+ op->op == IPP_ANY_OPERATION)
+ {
+ if ((op = cupsdFindPolicyOp(pol, IPP_SEND_DOCUMENT)) != NULL &&
+ op->op != IPP_ANY_OPERATION)
+ {
+ /*
+ * Add a new limit for Cancel-My-Jobs using the Send-Document limit as
+ * a template...
+ */
+
+ cupsdLogMessage(CUPSD_LOG_WARN,
+ "No limit for Cancel-My-Jobs defined in policy %s "
+ "- using Send-Document's policy.", pol->name);
+
+ cupsdAddPolicyOp(pol, op, IPP_CANCEL_MY_JOBS);
+ }
+ else
+ cupsdLogMessage(CUPSD_LOG_WARN,
+ "No limit for Cancel-My-Jobs defined in policy %s "
+ "and no suitable template found.", pol->name);
+ }
+
+ if ((op = cupsdFindPolicyOp(pol, IPP_CLOSE_JOB)) == NULL ||
+ op->op == IPP_ANY_OPERATION)
+ {
+ if ((op = cupsdFindPolicyOp(pol, IPP_SEND_DOCUMENT)) != NULL &&
+ op->op != IPP_ANY_OPERATION)
+ {
+ /*
+ * Add a new limit for Close-Job using the Send-Document limit as a
+ * template...
+ */
+
+ cupsdLogMessage(CUPSD_LOG_WARN,
+ "No limit for Close-Job defined in policy %s "
+ "- using Send-Document's policy.", pol->name);
+
+ cupsdAddPolicyOp(pol, op, IPP_CLOSE_JOB);
+ }
+ else
+ cupsdLogMessage(CUPSD_LOG_WARN,
+ "No limit for Close-Job defined in policy %s "
+ "and no suitable template found.", pol->name);
+ }
+
+ if ((op = cupsdFindPolicyOp(pol, CUPS_GET_DOCUMENT)) == NULL ||
+ op->op == IPP_ANY_OPERATION)
+ {
+ if ((op = cupsdFindPolicyOp(pol, IPP_SEND_DOCUMENT)) != NULL &&
+ op->op != IPP_ANY_OPERATION)
+ {
+ /*
+ * Add a new limit for CUPS-Get-Document using the Send-Document
+ * limit as a template...
+ */
+
+ cupsdLogMessage(CUPSD_LOG_WARN,
+ "No limit for CUPS-Get-Document defined in policy %s "
+ "- using Send-Document's policy.", pol->name);
+
+ cupsdAddPolicyOp(pol, op, CUPS_GET_DOCUMENT);
+ }
+ else
+ cupsdLogMessage(CUPSD_LOG_WARN,
+ "No limit for CUPS-Get-Document defined in policy %s "
+ "and no suitable template found.", pol->name);
+ }
+
+ /*
+ * Verify we have JobPrivateAccess, JobPrivateValues,
+ * SubscriptionPrivateAccess, and SubscriptionPrivateValues in the policy.
+ */
+
+ if (!pol->job_access)
+ {
+ cupsdLogMessage(CUPSD_LOG_WARN,
+ "No JobPrivateAccess defined in policy %s "
+ "- using defaults.", pol->name);
+ cupsdAddString(&(pol->job_access), "@OWNER");
+ cupsdAddString(&(pol->job_access), "@SYSTEM");
+ }
+
+ if (!pol->job_attrs)
+ {
+ cupsdLogMessage(CUPSD_LOG_WARN,
+ "No JobPrivateValues defined in policy %s "
+ "- using defaults.", pol->name);
+ cupsdAddString(&(pol->job_attrs), "job-name");
+ cupsdAddString(&(pol->job_attrs), "job-originating-host-name");
+ cupsdAddString(&(pol->job_attrs), "job-originating-user-name");
+ }
+
+ if (!pol->sub_access)
+ {
+ cupsdLogMessage(CUPSD_LOG_WARN,
+ "No SubscriptionPrivateAccess defined in policy %s "
+ "- using defaults.", pol->name);
+ cupsdAddString(&(pol->sub_access), "@OWNER");
+ cupsdAddString(&(pol->sub_access), "@SYSTEM");
+ }
+
+ if (!pol->sub_attrs)
+ {
+ cupsdLogMessage(CUPSD_LOG_WARN,
+ "No SubscriptionPrivateValues defined in policy %s "
+ "- using defaults.", pol->name);
+ cupsdAddString(&(pol->sub_attrs), "notify-events");
+ cupsdAddString(&(pol->sub_attrs), "notify-pull-method");
+ cupsdAddString(&(pol->sub_attrs), "notify-recipient-uri");
+ cupsdAddString(&(pol->sub_attrs), "notify-subscriber-user-name");
+ cupsdAddString(&(pol->sub_attrs), "notify-user-data");
+ }
+}
+
+
+/*
+ * End of "$Id: conf.c 9352 2010-11-06 04:55:26Z mike $".
*/
diff --git a/scheduler/conf.h b/scheduler/conf.h
index d1cab69a1..c98e89a00 100644
--- a/scheduler/conf.h
+++ b/scheduler/conf.h
@@ -1,7 +1,7 @@
/*
* "$Id: conf.h 7935 2008-09-11 01:54:11Z mike $"
*
- * Configuration file definitions for CUPS.
+ * Configuration file definitions for the CUPS scheduler.
*
* Copyright 2007-2010 by Apple Inc.
* Copyright 1997-2007 by Easy Software Products, all rights reserved.
diff --git a/scheduler/cups-deviced.c b/scheduler/cups-deviced.c
index 547a032d0..a7195985d 100644
--- a/scheduler/cups-deviced.c
+++ b/scheduler/cups-deviced.c
@@ -1,9 +1,9 @@
/*
* "$Id: cups-deviced.c 7816 2008-07-30 20:53:31Z mike $"
*
- * Device scanning mini-daemon for the Common UNIX Printing System (CUPS).
+ * Device scanning mini-daemon for CUPS.
*
- * Copyright 2007-2009 by Apple Inc.
+ * Copyright 2007-2010 by Apple Inc.
* Copyright 1997-2006 by Easy Software Products.
*
* These coded instructions, statements, and computer programs are the
diff --git a/scheduler/cupsd.h b/scheduler/cupsd.h
index 1c5ce2560..f1ba5cc7c 100644
--- a/scheduler/cupsd.h
+++ b/scheduler/cupsd.h
@@ -177,8 +177,10 @@ VAR int Launchd VALUE(0);
* Prototypes...
*/
+extern int cupsdAddString(cups_array_t **a, const char *s);
extern void cupsdCheckProcess(void);
extern void cupsdClearString(char **s);
+extern void cupsdFreeStrings(cups_array_t **a);
extern void cupsdHoldSignals(void);
extern void cupsdReleaseSignals(void);
extern void cupsdSetString(char **s, const char *v);
diff --git a/scheduler/cupsfilter.c b/scheduler/cupsfilter.c
index b40cc5564..e2e7bee84 100644
--- a/scheduler/cupsfilter.c
+++ b/scheduler/cupsfilter.c
@@ -1,7 +1,7 @@
/*
* "$Id: cupsfilter.c 7952 2008-09-17 00:56:20Z mike $"
*
- * CUPS filtering program for CUPS.
+ * Filtering program for CUPS.
*
* Copyright 2007-2010 by Apple Inc.
* Copyright 1997-2006 by Easy Software Products, all rights reserved.
diff --git a/scheduler/dirsvc.c b/scheduler/dirsvc.c
index 581ab6763..2f7f0e6c4 100644
--- a/scheduler/dirsvc.c
+++ b/scheduler/dirsvc.c
@@ -1,7 +1,7 @@
/*
* "$Id: dirsvc.c 7933 2008-09-11 00:44:58Z mike $"
*
- * Directory services routines for the Common UNIX Printing System (CUPS).
+ * Directory services routines for the CUPS scheduler.
*
* Copyright 2007-2010 by Apple Inc.
* Copyright 1997-2007 by Easy Software Products, all rights reserved.
@@ -634,7 +634,7 @@ cupsdLoadRemoteCache(void)
if (value)
{
p->deny_users = 0;
- cupsdAddPrinterUser(p, value);
+ cupsdAddString(&(p->users), value);
}
else
cupsdLogMessage(CUPSD_LOG_ERROR,
@@ -645,7 +645,7 @@ cupsdLoadRemoteCache(void)
if (value)
{
p->deny_users = 1;
- cupsdAddPrinterUser(p, value);
+ cupsdAddString(&(p->users), value);
}
else
cupsdLogMessage(CUPSD_LOG_ERROR,
@@ -728,7 +728,8 @@ cupsdSaveRemoteCache(void)
int i; /* Looping var */
cups_file_t *fp; /* printers.conf file */
char temp[1024], /* Temporary string */
- value[2048]; /* Value 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 */
@@ -829,9 +830,10 @@ cupsdSaveRemoteCache(void)
printer->job_sheets[1]);
cupsFilePutConf(fp, "JobSheets", value);
- for (i = 0; i < printer->num_users; i ++)
- cupsFilePutConf(fp, printer->deny_users ? "DenyUser" : "AllowUser",
- printer->users[i]);
+ for (name = (char *)cupsArrayFirst(printer->users);
+ name;
+ name = (char *)cupsArrayNext(printer->users))
+ cupsFilePutConf(fp, printer->deny_users ? "DenyUser" : "AllowUser", name);
for (i = printer->num_options, option = printer->options;
i > 0;
@@ -5194,24 +5196,20 @@ update_cups_browse(void)
case CUPSD_AUTH_ALLOW : /* Order Deny,Allow */
auth = CUPSD_AUTH_ALLOW;
- if (cupsdCheckAuth(address, srcname, len,
- BrowseACL->num_deny, BrowseACL->deny))
+ if (cupsdCheckAuth(address, srcname, len, BrowseACL->deny))
auth = CUPSD_AUTH_DENY;
- if (cupsdCheckAuth(address, srcname, len,
- BrowseACL->num_allow, BrowseACL->allow))
+ if (cupsdCheckAuth(address, srcname, len, BrowseACL->allow))
auth = CUPSD_AUTH_ALLOW;
break;
case CUPSD_AUTH_DENY : /* Order Allow,Deny */
auth = CUPSD_AUTH_DENY;
- if (cupsdCheckAuth(address, srcname, len,
- BrowseACL->num_allow, BrowseACL->allow))
+ if (cupsdCheckAuth(address, srcname, len, BrowseACL->allow))
auth = CUPSD_AUTH_ALLOW;
- if (cupsdCheckAuth(address, srcname, len,
- BrowseACL->num_deny, BrowseACL->deny))
+ if (cupsdCheckAuth(address, srcname, len, BrowseACL->deny))
auth = CUPSD_AUTH_DENY;
break;
}
@@ -5323,7 +5321,7 @@ update_cups_browse(void)
*/
for (i = 0; i < NumRelays; i ++)
- if (cupsdCheckAuth(address, srcname, len, 1, &(Relays[i].from)))
+ if (cupsdCheckAuth(address, srcname, len, Relays[i].from))
if (sendto(BrowseSocket, packet, bytes, 0,
(struct sockaddr *)&(Relays[i].to),
httpAddrLength(&(Relays[i].to))) <= 0)
diff --git a/scheduler/dirsvc.h b/scheduler/dirsvc.h
index c17a25406..cc4eb2047 100644
--- a/scheduler/dirsvc.h
+++ b/scheduler/dirsvc.h
@@ -1,10 +1,9 @@
/*
* "$Id: dirsvc.h 7933 2008-09-11 00:44:58Z mike $"
*
- * Directory services definitions for the Common UNIX Printing System
- * (CUPS) scheduler.
+ * Directory services definitions for the CUPS scheduler.
*
- * Copyright 2007-2009 by Apple Inc.
+ * Copyright 2007-2010 by Apple Inc.
* Copyright 1997-2007 by Easy Software Products, all rights reserved.
*
* These coded instructions, statements, and computer programs are the
@@ -62,7 +61,7 @@ typedef struct
typedef struct
{
- cupsd_authmask_t from; /* Source address/name mask */
+ cups_array_t *from; /* Source address/name mask(s) */
http_addr_t to; /* Destination address */
} cupsd_dirsvc_relay_t;
diff --git a/scheduler/env.c b/scheduler/env.c
index 94d7c355b..9cf6ff26f 100644
--- a/scheduler/env.c
+++ b/scheduler/env.c
@@ -1,9 +1,9 @@
/*
* "$Id: env.c 7673 2008-06-18 22:31:26Z mike $"
*
- * Environment management routines for the Common UNIX Printing System (CUPS).
+ * Environment management routines for the CUPS scheduler.
*
- * Copyright 2007 by Apple Inc.
+ * Copyright 2007-2010 by Apple Inc.
* Copyright 1997-2006 by Easy Software Products, all rights reserved.
*
* These coded instructions, statements, and computer programs are the
diff --git a/scheduler/ipp.c b/scheduler/ipp.c
index b1049b1ff..207596c08 100644
--- a/scheduler/ipp.c
+++ b/scheduler/ipp.c
@@ -167,7 +167,8 @@ 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);
+ ipp_tag_t group, int quickcopy,
+ cups_array_t *exclude);
static int copy_banner(cupsd_client_t *con, cupsd_job_t *job,
const char *name);
static int copy_file(const char *from, const char *to);
@@ -175,13 +176,14 @@ static int copy_model(cupsd_client_t *con, const char *from,
const char *to);
static void copy_job_attrs(cupsd_client_t *con,
cupsd_job_t *job,
- cups_array_t *ra);
+ cups_array_t *ra, cups_array_t *exclude);
static void copy_printer_attrs(cupsd_client_t *con,
cupsd_printer_t *printer,
cups_array_t *ra);
static void copy_subscription_attrs(cupsd_client_t *con,
cupsd_subscription_t *sub,
- cups_array_t *ra);
+ cups_array_t *ra,
+ cups_array_t *exclude);
static void create_job(cupsd_client_t *con, ipp_attribute_t *uri);
static cups_array_t *create_requested_array(ipp_t *request);
static void create_subscription(cupsd_client_t *con, ipp_attribute_t *uri);
@@ -4396,8 +4398,8 @@ static int /* O - 1 if OK, 0 if forbidden,
check_quotas(cupsd_client_t *con, /* I - Client connection */
cupsd_printer_t *p) /* I - Printer or class */
{
- int i; /* Looping var */
- char username[33]; /* Username */
+ char username[33], /* Username */
+ *name; /* Current user name */
cupsd_quota_t *q; /* Quota data */
#ifdef HAVE_MBR_UID_TO_UUID
/*
@@ -4464,10 +4466,10 @@ check_quotas(cupsd_client_t *con, /* I - Client connection */
* Check against users...
*/
- if (p->num_users == 0 && p->k_limit == 0 && p->page_limit == 0)
+ if (cupsArrayCount(p->users) == 0 && p->k_limit == 0 && p->page_limit == 0)
return (1);
- if (p->num_users)
+ if (cupsArrayCount(p->users))
{
#ifdef HAVE_MBR_UID_TO_UUID
/*
@@ -4498,21 +4500,22 @@ check_quotas(cupsd_client_t *con, /* I - Client connection */
endpwent();
#endif /* HAVE_MBR_UID_TO_UUID */
- for (i = 0; i < p->num_users; i ++)
- if (p->users[i][0] == '@')
+ for (name = (char *)cupsArrayFirst(p->users);
+ name;
+ name = (char *)cupsArrayNext(p->users))
+ if (name[0] == '@')
{
/*
* Check group membership...
*/
#ifdef HAVE_MBR_UID_TO_UUID
- if (p->users[i][1] == '#')
+ if (name[1] == '#')
{
- if (uuid_parse((char *)p->users[i] + 2, grp_uuid))
+ if (uuid_parse(name + 2, grp_uuid))
uuid_clear(grp_uuid);
}
- else if ((mbr_err = mbr_group_name_to_uuid((char *)p->users[i] + 1,
- grp_uuid)) != 0)
+ else if ((mbr_err = mbr_group_name_to_uuid(name + 1, grp_uuid)) != 0)
{
/*
* Invalid ACL entries are ignored for matching; just record a
@@ -4521,10 +4524,10 @@ check_quotas(cupsd_client_t *con, /* I - Client connection */
cupsdLogMessage(CUPSD_LOG_DEBUG,
"check_quotas: UUID lookup failed for ACL entry "
- "\"%s\" (err=%d)", p->users[i], mbr_err);
+ "\"%s\" (err=%d)", name, mbr_err);
cupsdLogMessage(CUPSD_LOG_WARN,
"Access control entry \"%s\" not a valid group name; "
- "entry ignored", p->users[i]);
+ "entry ignored", name);
}
if ((mbr_err = mbr_check_membership(usr_uuid, grp_uuid,
@@ -4536,7 +4539,7 @@ check_quotas(cupsd_client_t *con, /* I - Client connection */
cupsdLogMessage(CUPSD_LOG_DEBUG,
"check_quotas: group \"%s\" membership check "
- "failed (err=%d)", p->users[i] + 1, mbr_err);
+ "failed (err=%d)", name + 1, mbr_err);
is_member = 0;
}
@@ -4548,20 +4551,19 @@ check_quotas(cupsd_client_t *con, /* I - Client connection */
break;
#else
- if (cupsdCheckGroup(username, pw, p->users[i] + 1))
+ if (cupsdCheckGroup(username, pw, name + 1))
break;
#endif /* HAVE_MBR_UID_TO_UUID */
}
#ifdef HAVE_MBR_UID_TO_UUID
else
{
- if (p->users[i][0] == '#')
+ if (name[0] == '#')
{
- if (uuid_parse((char *)p->users[i] + 1, usr2_uuid))
+ if (uuid_parse(name + 1, usr2_uuid))
uuid_clear(usr2_uuid);
}
- else if ((mbr_err = mbr_user_name_to_uuid((char *)p->users[i],
- usr2_uuid)) != 0)
+ else if ((mbr_err = mbr_user_name_to_uuid(name, usr2_uuid)) != 0)
{
/*
* Invalid ACL entries are ignored for matching; just record a
@@ -4570,21 +4572,21 @@ check_quotas(cupsd_client_t *con, /* I - Client connection */
cupsdLogMessage(CUPSD_LOG_DEBUG,
"check_quotas: UUID lookup failed for ACL entry "
- "\"%s\" (err=%d)", p->users[i], mbr_err);
+ "\"%s\" (err=%d)", name, mbr_err);
cupsdLogMessage(CUPSD_LOG_WARN,
"Access control entry \"%s\" not a valid user name; "
- "entry ignored", p->users[i]);
+ "entry ignored", name);
}
if (!uuid_compare(usr_uuid, usr2_uuid))
break;
}
#else
- else if (!strcasecmp(username, p->users[i]))
+ else if (!strcasecmp(username, name))
break;
#endif /* HAVE_MBR_UID_TO_UUID */
- if ((i < p->num_users) == p->deny_users)
+ if ((name != NULL) == p->deny_users)
{
cupsdLogMessage(CUPSD_LOG_INFO,
"Denying user \"%s\" access to printer \"%s\"...",
@@ -4940,7 +4942,8 @@ copy_attrs(ipp_t *to, /* I - Destination request */
ipp_t *from, /* I - Source request */
cups_array_t *ra, /* I - Requested attributes */
ipp_tag_t group, /* I - Group to copy */
- int quickcopy) /* I - Do a quick copy? */
+ int quickcopy, /* I - Do a quick copy? */
+ cups_array_t *exclude) /* I - Attributes to exclude? */
{
ipp_attribute_t *fromattr; /* Source attribute */
@@ -4962,6 +4965,23 @@ copy_attrs(ipp_t *to, /* I - Destination request */
fromattr->group_tag != IPP_TAG_ZERO) || !fromattr->name)
continue;
+ if (exclude &&
+ (cupsArrayFind(exclude, fromattr->name) ||
+ cupsArrayFind(exclude, "all")))
+ {
+ /*
+ * We need to exclude this attribute for security reasons; we require the
+ * job-id and job-printer-uri attributes regardless of the security
+ * settings for IPP conformance.
+ *
+ * Subscription attribute security is handled by copy_subscription_attrs().
+ */
+
+ if (strcmp(fromattr->name, "job-id") &&
+ strcmp(fromattr->name, "job-printer-uri"))
+ continue;
+ }
+
if (!ra || cupsArrayFind(ra, fromattr->name))
{
/*
@@ -5608,7 +5628,8 @@ copy_model(cupsd_client_t *con, /* I - Client connection */
static void
copy_job_attrs(cupsd_client_t *con, /* I - Client connection */
cupsd_job_t *job, /* I - Job */
- cups_array_t *ra) /* I - Requested attributes array */
+ cups_array_t *ra, /* I - Requested attributes array */
+ cups_array_t *exclude) /* I - Private attributes array */
{
char job_uri[HTTP_MAX_URI]; /* Job URI */
@@ -5621,26 +5642,34 @@ copy_job_attrs(cupsd_client_t *con, /* I - Client connection */
con->servername, con->serverport, "/jobs/%d",
job->id);
- if (!ra || cupsArrayFind(ra, "document-count"))
- ippAddInteger(con->response, IPP_TAG_JOB, IPP_TAG_INTEGER,
- "document-count", job->num_files);
+ if (!cupsArrayFind(exclude, "all"))
+ {
+ if ((!exclude || !cupsArrayFind(exclude, "document-count")) &&
+ (!ra || cupsArrayFind(ra, "document-count")))
+ ippAddInteger(con->response, IPP_TAG_JOB, IPP_TAG_INTEGER,
+ "document-count", job->num_files);
- if (!ra || cupsArrayFind(ra, "job-media-progress"))
- ippAddInteger(con->response, IPP_TAG_JOB, IPP_TAG_INTEGER,
- "job-media-progress", job->progress);
+ if ((!exclude || !cupsArrayFind(exclude, "job-media-progress")) &&
+ (!ra || cupsArrayFind(ra, "job-media-progress")))
+ ippAddInteger(con->response, IPP_TAG_JOB, IPP_TAG_INTEGER,
+ "job-media-progress", job->progress);
- if (!ra || cupsArrayFind(ra, "job-more-info"))
- ippAddString(con->response, IPP_TAG_JOB, IPP_TAG_URI,
- "job-more-info", NULL, job_uri);
+ if ((!exclude || !cupsArrayFind(exclude, "job-more-info")) &&
+ (!ra || cupsArrayFind(ra, "job-more-info")))
+ ippAddString(con->response, IPP_TAG_JOB, IPP_TAG_URI,
+ "job-more-info", NULL, job_uri);
- if (job->state_value > IPP_JOB_PROCESSING &&
- (!ra || cupsArrayFind(ra, "job-preserved")))
- ippAddBoolean(con->response, IPP_TAG_JOB, "job-preserved",
- job->num_files > 0);
+ if (job->state_value > IPP_JOB_PROCESSING &&
+ (!exclude || !cupsArrayFind(exclude, "job-preserved")) &&
+ (!ra || cupsArrayFind(ra, "job-preserved")))
+ ippAddBoolean(con->response, IPP_TAG_JOB, "job-preserved",
+ job->num_files > 0);
- if (!ra || cupsArrayFind(ra, "job-printer-up-time"))
- ippAddInteger(con->response, IPP_TAG_JOB, IPP_TAG_INTEGER,
- "job-printer-up-time", time(NULL));
+ if ((!exclude || !cupsArrayFind(exclude, "job-printer-up-time")) &&
+ (!ra || cupsArrayFind(ra, "job-printer-up-time")))
+ ippAddInteger(con->response, IPP_TAG_JOB, IPP_TAG_INTEGER,
+ "job-printer-up-time", time(NULL));
+ }
if (!ra || cupsArrayFind(ra, "job-state-reasons"))
add_job_state_reasons(con, job);
@@ -5649,7 +5678,7 @@ copy_job_attrs(cupsd_client_t *con, /* I - Client connection */
ippAddString(con->response, IPP_TAG_JOB, IPP_TAG_URI,
"job-uri", NULL, job_uri);
- copy_attrs(con->response, job->attrs, ra, IPP_TAG_JOB, 0);
+ copy_attrs(con->response, job->attrs, ra, IPP_TAG_JOB, 0, exclude);
}
@@ -5821,7 +5850,7 @@ copy_printer_attrs(
for (i = 0; i < printer->num_history; i ++)
copy_attrs(history->values[i].collection = ippNew(), printer->history[i],
- NULL, IPP_TAG_ZERO, 0);
+ NULL, IPP_TAG_ZERO, 0, NULL);
}
if (!ra || cupsArrayFind(ra, "printer-state-message"))
@@ -5875,10 +5904,10 @@ copy_printer_attrs(
if (!ra || cupsArrayFind(ra, "queued-job-count"))
add_queued_job_count(con, printer);
- copy_attrs(con->response, printer->attrs, ra, IPP_TAG_ZERO, 0);
+ copy_attrs(con->response, printer->attrs, ra, IPP_TAG_ZERO, 0, NULL);
if (printer->ppd_attrs)
- copy_attrs(con->response, printer->ppd_attrs, ra, IPP_TAG_ZERO, 0);
- copy_attrs(con->response, CommonData, ra, IPP_TAG_ZERO, IPP_TAG_COPY);
+ copy_attrs(con->response, printer->ppd_attrs, ra, IPP_TAG_ZERO, 0, NULL);
+ copy_attrs(con->response, CommonData, ra, IPP_TAG_ZERO, IPP_TAG_COPY, NULL);
}
@@ -5890,7 +5919,8 @@ static void
copy_subscription_attrs(
cupsd_client_t *con, /* I - Client connection */
cupsd_subscription_t *sub, /* I - Subscription */
- cups_array_t *ra) /* I - Requested attributes array */
+ cups_array_t *ra, /* I - Requested attributes array */
+ cups_array_t *exclude) /* I - Private attributes array */
{
ipp_attribute_t *attr; /* Current attribute */
char printer_uri[HTTP_MAX_URI];
@@ -5900,56 +5930,92 @@ copy_subscription_attrs(
const char *name; /* Current event name */
+ cupsdLogMessage(CUPSD_LOG_DEBUG2,
+ "copy_subscription_attrs(con=%p, sub=%p, ra=%p, exclude=%p)",
+ con, sub, ra, exclude);
+
/*
* Copy the subscription attributes to the response using the
* requested-attributes attribute that may be provided by the client.
*/
- if (!ra || cupsArrayFind(ra, "notify-events"))
+ if (!exclude || !cupsArrayFind(exclude, "all"))
{
- if ((name = cupsdEventName((cupsd_eventmask_t)sub->mask)) != NULL)
+ if ((!exclude || !cupsArrayFind(exclude, "notify-events")) &&
+ (!ra || cupsArrayFind(ra, "notify-events")))
{
- /*
- * Simple event list...
- */
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "copy_subscription_attrs: notify-events");
- ippAddString(con->response, IPP_TAG_SUBSCRIPTION,
- (ipp_tag_t)(IPP_TAG_KEYWORD | IPP_TAG_COPY),
- "notify-events", NULL, name);
- }
- else
- {
- /*
- * Complex event list...
- */
+ if ((name = cupsdEventName((cupsd_eventmask_t)sub->mask)) != NULL)
+ {
+ /*
+ * Simple event list...
+ */
+
+ ippAddString(con->response, IPP_TAG_SUBSCRIPTION,
+ (ipp_tag_t)(IPP_TAG_KEYWORD | IPP_TAG_COPY),
+ "notify-events", NULL, name);
+ }
+ else
+ {
+ /*
+ * Complex event list...
+ */
- for (mask = 1, count = 0; mask < CUPSD_EVENT_ALL; mask <<= 1)
- if (sub->mask & mask)
- count ++;
+ for (mask = 1, count = 0; mask < CUPSD_EVENT_ALL; mask <<= 1)
+ if (sub->mask & mask)
+ count ++;
- attr = ippAddStrings(con->response, IPP_TAG_SUBSCRIPTION,
- (ipp_tag_t)(IPP_TAG_KEYWORD | IPP_TAG_COPY),
- "notify-events", count, NULL, NULL);
+ attr = ippAddStrings(con->response, IPP_TAG_SUBSCRIPTION,
+ (ipp_tag_t)(IPP_TAG_KEYWORD | IPP_TAG_COPY),
+ "notify-events", count, NULL, NULL);
- for (mask = 1, count = 0; mask < CUPSD_EVENT_ALL; mask <<= 1)
- if (sub->mask & mask)
- {
- attr->values[count].string.text =
- (char *)cupsdEventName((cupsd_eventmask_t)mask);
+ for (mask = 1, count = 0; mask < CUPSD_EVENT_ALL; mask <<= 1)
+ if (sub->mask & mask)
+ {
+ attr->values[count].string.text =
+ (char *)cupsdEventName((cupsd_eventmask_t)mask);
- count ++;
- }
+ count ++;
+ }
+ }
}
+
+ if ((!exclude || !cupsArrayFind(exclude, "notify-lease-duration")) &&
+ (!sub->job && (!ra || cupsArrayFind(ra, "notify-lease-duration"))))
+ ippAddInteger(con->response, IPP_TAG_SUBSCRIPTION, IPP_TAG_INTEGER,
+ "notify-lease-duration", sub->lease);
+
+ if ((!exclude || !cupsArrayFind(exclude, "notify-recipient-uri")) &&
+ (sub->recipient && (!ra || cupsArrayFind(ra, "notify-recipient-uri"))))
+ ippAddString(con->response, IPP_TAG_SUBSCRIPTION, IPP_TAG_URI,
+ "notify-recipient-uri", NULL, sub->recipient);
+ else if ((!exclude || !cupsArrayFind(exclude, "notify-pull-method")) &&
+ (!ra || cupsArrayFind(ra, "notify-pull-method")))
+ ippAddString(con->response, IPP_TAG_SUBSCRIPTION, IPP_TAG_KEYWORD,
+ "notify-pull-method", NULL, "ippget");
+
+ if ((!exclude || !cupsArrayFind(exclude, "notify-subscriber-user-name")) &&
+ (!ra || cupsArrayFind(ra, "notify-subscriber-user-name")))
+ ippAddString(con->response, IPP_TAG_SUBSCRIPTION, IPP_TAG_NAME,
+ "notify-subscriber-user-name", NULL, sub->owner);
+
+ if ((!exclude || !cupsArrayFind(exclude, "notify-time-interval")) &&
+ (!ra || cupsArrayFind(ra, "notify-time-interval")))
+ ippAddInteger(con->response, IPP_TAG_SUBSCRIPTION, IPP_TAG_INTEGER,
+ "notify-time-interval", sub->interval);
+
+ if (sub->user_data_len > 0 &&
+ (!exclude || !cupsArrayFind(exclude, "notify-user-data")) &&
+ (!ra || cupsArrayFind(ra, "notify-user-data")))
+ ippAddOctetString(con->response, IPP_TAG_SUBSCRIPTION, "notify-user-data",
+ sub->user_data, sub->user_data_len);
}
if (sub->job && (!ra || cupsArrayFind(ra, "notify-job-id")))
ippAddInteger(con->response, IPP_TAG_SUBSCRIPTION, IPP_TAG_INTEGER,
"notify-job-id", sub->job->id);
- if (!sub->job && (!ra || cupsArrayFind(ra, "notify-lease-duration")))
- ippAddInteger(con->response, IPP_TAG_SUBSCRIPTION, IPP_TAG_INTEGER,
- "notify-lease-duration", sub->lease);
-
if (sub->dest && (!ra || cupsArrayFind(ra, "notify-printer-uri")))
{
httpAssembleURIf(HTTP_URI_CODING_ALL, printer_uri, sizeof(printer_uri),
@@ -5959,28 +6025,9 @@ copy_subscription_attrs(
"notify-printer-uri", NULL, printer_uri);
}
- if (sub->recipient && (!ra || cupsArrayFind(ra, "notify-recipient-uri")))
- ippAddString(con->response, IPP_TAG_SUBSCRIPTION, IPP_TAG_URI,
- "notify-recipient-uri", NULL, sub->recipient);
- else if (!ra || cupsArrayFind(ra, "notify-pull-method"))
- ippAddString(con->response, IPP_TAG_SUBSCRIPTION, IPP_TAG_KEYWORD,
- "notify-pull-method", NULL, "ippget");
-
- if (!ra || cupsArrayFind(ra, "notify-subscriber-user-name"))
- ippAddString(con->response, IPP_TAG_SUBSCRIPTION, IPP_TAG_NAME,
- "notify-subscriber-user-name", NULL, sub->owner);
-
if (!ra || cupsArrayFind(ra, "notify-subscription-id"))
ippAddInteger(con->response, IPP_TAG_SUBSCRIPTION, IPP_TAG_INTEGER,
"notify-subscription-id", sub->id);
-
- if (!ra || cupsArrayFind(ra, "notify-time-interval"))
- ippAddInteger(con->response, IPP_TAG_SUBSCRIPTION, IPP_TAG_INTEGER,
- "notify-time-interval", sub->interval);
-
- if (sub->user_data_len > 0 && (!ra || cupsArrayFind(ra, "notify-user-data")))
- ippAddOctetString(con->response, IPP_TAG_SUBSCRIPTION, "notify-user-data",
- sub->user_data, sub->user_data_len);
}
@@ -7004,12 +7051,14 @@ get_job_attrs(cupsd_client_t *con, /* I - Client connection */
int jobid; /* Job ID */
cupsd_job_t *job; /* Current job */
cupsd_printer_t *printer; /* Current printer */
- char scheme[HTTP_MAX_URI], /* Method portion of URI */
+ cupsd_policy_t *policy; /* Current security policy */
+ char scheme[HTTP_MAX_URI], /* Scheme portion of URI */
username[HTTP_MAX_URI], /* Username portion of URI */
host[HTTP_MAX_URI], /* Host portion of URI */
resource[HTTP_MAX_URI]; /* Resource portion of URI */
int port; /* Port portion of URI */
- cups_array_t *ra; /* Requested attributes array */
+ cups_array_t *ra, /* Requested attributes array */
+ *exclude; /* Private attributes array */
cupsdLogMessage(CUPSD_LOG_DEBUG2, "get_job_attrs(%p[%d], %s)", con,
@@ -7082,20 +7131,18 @@ get_job_attrs(cupsd_client_t *con, /* I - Client connection */
printer = cupsdFindDest(job->dest);
if (printer)
- {
- if ((status = cupsdCheckPolicy(printer->op_policy_ptr, con,
- NULL)) != HTTP_OK)
- {
- send_http_error(con, status, printer);
- return;
- }
- }
- else if ((status = cupsdCheckPolicy(DefaultPolicyPtr, con, NULL)) != HTTP_OK)
+ policy = printer->op_policy_ptr;
+ else
+ policy = DefaultPolicyPtr;
+
+ if ((status = cupsdCheckPolicy(policy, con, job->username)) != HTTP_OK)
{
send_http_error(con, status, NULL);
return;
}
+ exclude = cupsdGetPrivateAttrs(policy, con, printer, job->username);
+
/*
* Copy attributes...
*/
@@ -7103,7 +7150,7 @@ get_job_attrs(cupsd_client_t *con, /* I - Client connection */
cupsdLoadJob(job);
ra = create_requested_array(con->request);
- copy_job_attrs(con, job, ra);
+ copy_job_attrs(con, job, ra, exclude);
cupsArrayDelete(ra);
con->response->request.status.status_code = IPP_OK;
@@ -7137,7 +7184,9 @@ get_jobs(cupsd_client_t *con, /* I - Client connection */
cupsd_job_t *job; /* Current job pointer */
cupsd_printer_t *printer; /* Printer */
cups_array_t *list; /* Which job list... */
- cups_array_t *ra; /* Requested attributes array */
+ cups_array_t *ra, /* Requested attributes array */
+ *exclude; /* Private attributes array */
+ cupsd_policy_t *policy; /* Current policy */
cupsdLogMessage(CUPSD_LOG_DEBUG2, "get_jobs(%p[%d], %s)", con, con->http.fd,
@@ -7200,15 +7249,11 @@ get_jobs(cupsd_client_t *con, /* I - Client connection */
*/
if (printer)
- {
- if ((status = cupsdCheckPolicy(printer->op_policy_ptr, con,
- NULL)) != HTTP_OK)
- {
- send_http_error(con, status, printer);
- return;
- }
- }
- else if ((status = cupsdCheckPolicy(DefaultPolicyPtr, con, NULL)) != HTTP_OK)
+ policy = printer->op_policy_ptr;
+ else
+ policy = DefaultPolicyPtr;
+
+ if ((status = cupsdCheckPolicy(policy, con, NULL)) != HTTP_OK)
{
send_http_error(con, status, NULL);
return;
@@ -7395,7 +7440,12 @@ get_jobs(cupsd_client_t *con, /* I - Client connection */
if (i > 0)
ippAddSeparator(con->response);
- copy_job_attrs(con, job, ra);
+ exclude = cupsdGetPrivateAttrs(job->printer ?
+ job->printer->op_policy_ptr :
+ policy, con, job->printer,
+ job->username);
+
+ copy_job_attrs(con, job, ra, exclude);
}
}
else
@@ -7451,7 +7501,12 @@ get_jobs(cupsd_client_t *con, /* I - Client connection */
count ++;
- copy_job_attrs(con, job, ra);
+ exclude = cupsdGetPrivateAttrs(job->printer ?
+ job->printer->op_policy_ptr :
+ policy, con, job->printer,
+ job->username);
+
+ copy_job_attrs(con, job, ra, exclude);
}
cupsdLogMessage(CUPSD_LOG_DEBUG2, "get_jobs: count=%d", count);
@@ -7577,7 +7632,7 @@ get_notifications(cupsd_client_t *con) /* I - Client connection */
* If we don't have any new events, nothing to do here...
*/
- if (min_seq > (sub->first_event_id + sub->num_events))
+ if (min_seq > (sub->first_event_id + cupsArrayCount(sub->events)))
continue;
/*
@@ -7589,12 +7644,13 @@ get_notifications(cupsd_client_t *con) /* I - Client connection */
else
j = min_seq - sub->first_event_id;
- for (; j < sub->num_events; j ++)
+ for (; j < cupsArrayCount(sub->events); j ++)
{
ippAddSeparator(con->response);
- copy_attrs(con->response, sub->events[j]->attrs, NULL,
- IPP_TAG_EVENT_NOTIFICATION, 0);
+ copy_attrs(con->response,
+ ((cupsd_event_t *)cupsArrayIndex(sub->events, j))->attrs, NULL,
+ IPP_TAG_EVENT_NOTIFICATION, 0, NULL);
}
}
}
@@ -8162,7 +8218,8 @@ get_printers(cupsd_client_t *con, /* I - Client connection */
* access...
*/
- if (printer->num_users && username && !user_allowed(printer, username))
+ if (cupsArrayCount(printer->users) && username &&
+ !user_allowed(printer, username))
continue;
/*
@@ -8199,7 +8256,9 @@ get_subscription_attrs(
{
http_status_t status; /* Policy status */
cupsd_subscription_t *sub; /* Subscription */
- cups_array_t *ra; /* Requested attributes array */
+ cupsd_policy_t *policy; /* Current security policy */
+ cups_array_t *ra, /* Requested attributes array */
+ *exclude; /* Private attributes array */
cupsdLogMessage(CUPSD_LOG_DEBUG2,
@@ -8225,14 +8284,19 @@ get_subscription_attrs(
* Check policy...
*/
- if ((status = cupsdCheckPolicy(sub->dest ? sub->dest->op_policy_ptr :
- DefaultPolicyPtr,
- con, sub->owner)) != HTTP_OK)
+ if (sub->dest)
+ policy = sub->dest->op_policy_ptr;
+ else
+ policy = DefaultPolicyPtr;
+
+ if ((status = cupsdCheckPolicy(policy, con, sub->owner)) != HTTP_OK)
{
send_http_error(con, status, sub->dest);
return;
}
+ exclude = cupsdGetPrivateAttrs(policy, con, sub->dest, sub->owner);
+
/*
* Copy the subscription attributes to the response using the
* requested-attributes attribute that may be provided by the client.
@@ -8240,7 +8304,7 @@ get_subscription_attrs(
ra = create_requested_array(con->request);
- copy_subscription_attrs(con, sub, ra);
+ copy_subscription_attrs(con, sub, ra, exclude);
cupsArrayDelete(ra);
@@ -8274,6 +8338,8 @@ get_subscriptions(cupsd_client_t *con, /* I - Client connection */
int port; /* Port portion of URI */
cupsd_job_t *job; /* Job pointer */
cupsd_printer_t *printer; /* Printer */
+ cupsd_policy_t *policy; /* Policy */
+ cups_array_t *exclude; /* Private attributes array */
cupsdLogMessage(CUPSD_LOG_DEBUG2,
@@ -8337,9 +8403,12 @@ get_subscriptions(cupsd_client_t *con, /* I - Client connection */
* Check policy...
*/
- if ((status = cupsdCheckPolicy(printer ? printer->op_policy_ptr :
- DefaultPolicyPtr,
- con, NULL)) != HTTP_OK)
+ if (printer)
+ policy = printer->op_policy_ptr;
+ else
+ policy = DefaultPolicyPtr;
+
+ if ((status = cupsdCheckPolicy(policy, con, NULL)) != HTTP_OK)
{
send_http_error(con, status, printer);
return;
@@ -8376,7 +8445,12 @@ get_subscriptions(cupsd_client_t *con, /* I - Client connection */
(!username[0] || !strcasecmp(username, sub->owner)))
{
ippAddSeparator(con->response);
- copy_subscription_attrs(con, sub, ra);
+
+ exclude = cupsdGetPrivateAttrs(sub->dest ? sub->dest->op_policy_ptr :
+ policy, con, sub->dest,
+ sub->owner);
+
+ copy_subscription_attrs(con, sub, ra, exclude);
count ++;
if (limit && count >= limit)
@@ -11198,7 +11272,7 @@ set_printer_defaults(
}
else if (!strcmp(attr->name, "requesting-user-name-allowed"))
{
- cupsdFreePrinterUsers(printer);
+ cupsdFreeStrings(&(printer->users));
printer->deny_users = 0;
@@ -11207,12 +11281,12 @@ set_printer_defaults(
strcmp(attr->values[0].string.text, "all")))
{
for (i = 0; i < attr->num_values; i ++)
- cupsdAddPrinterUser(printer, attr->values[i].string.text);
+ cupsdAddString(&(printer->users), attr->values[i].string.text);
}
}
else if (!strcmp(attr->name, "requesting-user-name-denied"))
{
- cupsdFreePrinterUsers(printer);
+ cupsdFreeStrings(&(printer->users));
printer->deny_users = 1;
@@ -11221,7 +11295,7 @@ set_printer_defaults(
strcmp(attr->values[0].string.text, "none")))
{
for (i = 0; i < attr->num_values; i ++)
- cupsdAddPrinterUser(printer, attr->values[i].string.text);
+ cupsdAddString(&(printer->users), attr->values[i].string.text);
}
}
else if (!strcmp(attr->name, "job-quota-period"))
@@ -11401,6 +11475,7 @@ static void
start_printer(cupsd_client_t *con, /* I - Client connection */
ipp_attribute_t *uri) /* I - Printer URI */
{
+ int i; /* Temporary variable */
http_status_t status; /* Policy status */
cups_ptype_t dtype; /* Destination type (printer/class) */
cupsd_printer_t *printer; /* Printer data */
@@ -11451,6 +11526,21 @@ start_printer(cupsd_client_t *con, /* I - Client connection */
cupsdCheckJobs();
+ /*
+ * Check quotas...
+ */
+
+ if ((i = check_quotas(con, printer)) < 0)
+ {
+ send_ipp_status(con, IPP_NOT_POSSIBLE, _("Quota limit reached."));
+ return;
+ }
+ else if (i == 0)
+ {
+ send_ipp_status(con, IPP_NOT_AUTHORIZED, _("Not allowed to print."));
+ return;
+ }
+
/*
* Everything was ok, so return OK status...
*/
@@ -11634,13 +11724,13 @@ static int /* O - 0 if not allowed, 1 if allowed */
user_allowed(cupsd_printer_t *p, /* I - Printer or class */
const char *username) /* I - Username */
{
- int i; /* Looping var */
struct passwd *pw; /* User password data */
char baseuser[256], /* Base username */
- *baseptr; /* Pointer to "@" in base username */
+ *baseptr, /* Pointer to "@" in base username */
+ *name; /* Current user name */
- if (p->num_users == 0)
+ if (cupsArrayCount(p->users) == 0)
return (1);
if (!strcmp(username, "root"))
@@ -11663,31 +11753,33 @@ user_allowed(cupsd_printer_t *p, /* I - Printer or class */
pw = getpwnam(username);
endpwent();
- for (i = 0; i < p->num_users; i ++)
+ for (name = (char *)cupsArrayFirst(p->users);
+ name;
+ name = (char *)cupsArrayNext(p->users))
{
- if (p->users[i][0] == '@')
+ if (name[0] == '@')
{
/*
* Check group membership...
*/
- if (cupsdCheckGroup(username, pw, p->users[i] + 1))
+ if (cupsdCheckGroup(username, pw, name + 1))
break;
}
- else if (p->users[i][0] == '#')
+ else if (name[0] == '#')
{
/*
* Check UUID...
*/
- if (cupsdCheckGroup(username, pw, p->users[i]))
+ if (cupsdCheckGroup(username, pw, name))
break;
}
- else if (!strcasecmp(username, p->users[i]))
+ else if (!strcasecmp(username, name))
break;
}
- return ((i < p->num_users) != p->deny_users);
+ return ((name != NULL) != p->deny_users);
}
diff --git a/scheduler/job.c b/scheduler/job.c
index cc395d311..a58ab311d 100644
--- a/scheduler/job.c
+++ b/scheduler/job.c
@@ -294,6 +294,9 @@ cupsdCheckJobs(void)
if (job->kill_time && job->kill_time <= curtime)
{
+ cupsdLogMessage(CUPSD_LOG_ERROR, "[Job %d] Stopping unresponsive job!",
+ job->id);
+
stop_job(job, CUPSD_JOB_FORCE);
continue;
}
@@ -2721,6 +2724,12 @@ finalize_job(cupsd_job_t *job, /* I - Job */
cupsdDestroyProfile(job->profile);
job->profile = NULL;
+ /*
+ * Clear the unresponsive job watchdog timer...
+ */
+
+ job->kill_time = 0;
+
/*
* Close pipes and status buffer...
*/
@@ -3068,7 +3077,7 @@ get_options(cupsd_job_t *job, /* I - Job */
output_mode = _PWG_OUTPUT_MODE_COLOR;
if ((attr = ippFindAttribute(job->attrs, "print-quality",
- IPP_TAG_INTEGER)) != NULL &&
+ IPP_TAG_ENUM)) != NULL &&
attr->values[0].integer >= IPP_QUALITY_DRAFT &&
attr->values[0].integer <= IPP_QUALITY_HIGH)
print_quality = attr->values[0].integer - IPP_QUALITY_DRAFT;
diff --git a/scheduler/job.h b/scheduler/job.h
index 16dd09ff7..2268886b0 100644
--- a/scheduler/job.h
+++ b/scheduler/job.h
@@ -1,9 +1,9 @@
/*
* "$Id: job.h 7883 2008-08-28 20:38:13Z mike $"
*
- * Print job definitions for the Common UNIX Printing System (CUPS) scheduler.
+ * Print job definitions for the CUPS scheduler.
*
- * Copyright 2007-2009 by Apple Inc.
+ * Copyright 2007-2010 by Apple Inc.
* Copyright 1997-2007 by Easy Software Products, all rights reserved.
*
* These coded instructions, statements, and computer programs are the
@@ -40,6 +40,7 @@ struct cupsd_job_s /**** Job request ****/
char *username; /* Printing user */
char *dest; /* Destination printer or class */
cups_ptype_t dtype; /* Destination type */
+ cupsd_printer_t *printer; /* Printer this job is assigned to */
int num_files; /* Number of files in job */
mime_type_t **filetypes; /* File types */
int *compressions; /* Compression status of each file */
@@ -68,7 +69,6 @@ struct cupsd_job_s /**** Job request ****/
/* Filter process IDs, 0 terminated */
int backend; /* Backend process ID */
int status; /* Status code from filters */
- cupsd_printer_t *printer; /* Printer this job is assigned to */
int tries; /* Number of tries for this job */
char *auth_username, /* AUTH_USERNAME environment variable,
* if any */
diff --git a/scheduler/listen.c b/scheduler/listen.c
index 85c807166..15af46f06 100644
--- a/scheduler/listen.c
+++ b/scheduler/listen.c
@@ -1,10 +1,9 @@
/*
* "$Id: listen.c 7918 2008-09-08 22:03:01Z mike $"
*
- * Server listening routines for the Common UNIX Printing System (CUPS)
- * scheduler.
+ * Server listening routines for the CUPS scheduler.
*
- * Copyright 2007-2009 by Apple Inc.
+ * Copyright 2007-2010 by Apple Inc.
* Copyright 1997-2006 by Easy Software Products, all rights reserved.
*
* These coded instructions, statements, and computer programs are the
diff --git a/scheduler/log.c b/scheduler/log.c
index 09bb273e9..80ee8e077 100644
--- a/scheduler/log.c
+++ b/scheduler/log.c
@@ -1,7 +1,7 @@
/*
* "$Id: log.c 7918 2008-09-08 22:03:01Z mike $"
*
- * Log file routines for the Common UNIX Printing System (CUPS).
+ * Log file routines for the CUPS scheduler.
*
* Copyright 2007-2010 by Apple Inc.
* Copyright 1997-2007 by Easy Software Products, all rights reserved.
diff --git a/scheduler/main.c b/scheduler/main.c
index 1c0bdf4f8..cbd6732d6 100644
--- a/scheduler/main.c
+++ b/scheduler/main.c
@@ -14,26 +14,29 @@
*
* Contents:
*
- * main() - Main entry for the CUPS scheduler.
- * cupsdClosePipe() - Close a pipe as necessary.
- * cupsdOpenPipe() - Create a pipe which is closed on exec.
- * cupsdHoldSignals() - Hold child and termination signals.
- * cupsdReleaseSignals() - Release signals for delivery.
- * cupsdSetString() - Set a string value.
- * cupsdSetStringf() - Set a formatted string value.
- * cupsd_clean_files() - Clean out old files.
- * launchd_checkin() - Check-in with launchd and collect the
- * listening fds.
- * launchd_checkout() - Check-out with launchd.
- * parent_handler() - Catch USR1/CHLD signals...
- * process_children() - Process all dead children...
- * select_timeout() - Calculate the select timeout value.
- * sigchld_handler() - Handle 'child' signals from old processes.
- * sighup_handler() - Handle 'hangup' signals to reconfigure the
- * scheduler.
- * sigterm_handler() - Handle 'terminate' signals that stop the
- * scheduler.
- * usage() - Show scheduler usage.
+ * main() - Main entry for the CUPS scheduler.
+ * cupsdAddString() - Copy and add a string to an array.
+ * cupsdCheckProcess() - Tell the main loop to check for dead children.
+ * cupsdClearString() - Clear a string.
+ * cupsdClosePipe() - Close a pipe as necessary.
+ * cupsdFreeStrings() - Free an array of strings.
+ * cupsdHoldSignals() - Hold child and termination signals.
+ * cupsdOpenPipe() - Create a pipe which is closed on exec.
+ * cupsdReleaseSignals() - Release signals for delivery.
+ * cupsdSetString() - Set a string value.
+ * cupsdSetStringf() - Set a formatted string value.
+ * cupsd_clean_files() - Clean out old files.
+ * launchd_checkin() - Check-in with launchd and collect the listening
+ * fds.
+ * launchd_checkout() - Update the launchd KeepAlive file as needed.
+ * parent_handler() - Catch USR1/CHLD signals...
+ * process_children() - Process all dead children...
+ * select_timeout() - Calculate the select timeout value.
+ * sigchld_handler() - Handle 'child' signals from old processes.
+ * sighup_handler() - Handle 'hangup' signals to reconfigure the
+ * scheduler.
+ * sigterm_handler() - Handle 'terminate' signals that stop the scheduler.
+ * usage() - Show scheduler usage.
*/
/*
@@ -1178,6 +1181,24 @@ main(int argc, /* I - Number of command-line args */
}
+/*
+ * 'cupsdAddString()' - Copy and add a string to an array.
+ */
+
+int /* O - 1 on success, 0 on failure */
+cupsdAddString(cups_array_t **a, /* IO - String array */
+ const char *s) /* I - String to copy and add */
+{
+ if (!*a)
+ *a = cupsArrayNew3((cups_array_func_t)strcmp, NULL,
+ (cups_ahash_func_t)NULL, 0,
+ (cups_acopy_func_t)_cupsStrAlloc,
+ (cups_afree_func_t)_cupsStrFree);
+
+ return (cupsArrayAdd(*a, (char *)s));
+}
+
+
/*
* 'cupsdCheckProcess()' - Tell the main loop to check for dead children.
*/
@@ -1193,6 +1214,21 @@ cupsdCheckProcess(void)
}
+/*
+ * 'cupsdClearString()' - Clear a string.
+ */
+
+void
+cupsdClearString(char **s) /* O - String value */
+{
+ if (s && *s)
+ {
+ _cupsStrFree(*s);
+ *s = NULL;
+ }
+}
+
+
/*
* 'cupsdClosePipe()' - Close a pipe as necessary.
*/
@@ -1218,6 +1254,49 @@ cupsdClosePipe(int *fds) /* I - Pipe file descriptors (2) */
}
+/*
+ * 'cupsdFreeStrings()' - Free an array of strings.
+ */
+
+void
+cupsdFreeStrings(cups_array_t **a) /* IO - String array */
+{
+ if (*a)
+ {
+ cupsArrayDelete(*a);
+ *a = NULL;
+ }
+}
+
+
+/*
+ * 'cupsdHoldSignals()' - Hold child and termination signals.
+ */
+
+void
+cupsdHoldSignals(void)
+{
+#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
+ sigset_t newmask; /* New POSIX signal mask */
+#endif /* HAVE_SIGACTION && !HAVE_SIGSET */
+
+
+ holdcount ++;
+ if (holdcount > 1)
+ return;
+
+#ifdef HAVE_SIGSET
+ sighold(SIGTERM);
+ sighold(SIGCHLD);
+#elif defined(HAVE_SIGACTION)
+ sigemptyset(&newmask);
+ sigaddset(&newmask, SIGTERM);
+ sigaddset(&newmask, SIGCHLD);
+ sigprocmask(SIG_BLOCK, &newmask, &holdmask);
+#endif /* HAVE_SIGSET */
+}
+
+
/*
* 'cupsdOpenPipe()' - Create a pipe which is closed on exec.
*/
@@ -1271,49 +1350,6 @@ cupsdOpenPipe(int *fds) /* O - Pipe file descriptors (2) */
}
-/*
- * 'cupsdClearString()' - Clear a string.
- */
-
-void
-cupsdClearString(char **s) /* O - String value */
-{
- if (s && *s)
- {
- _cupsStrFree(*s);
- *s = NULL;
- }
-}
-
-
-/*
- * 'cupsdHoldSignals()' - Hold child and termination signals.
- */
-
-void
-cupsdHoldSignals(void)
-{
-#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
- sigset_t newmask; /* New POSIX signal mask */
-#endif /* HAVE_SIGACTION && !HAVE_SIGSET */
-
-
- holdcount ++;
- if (holdcount > 1)
- return;
-
-#ifdef HAVE_SIGSET
- sighold(SIGTERM);
- sighold(SIGCHLD);
-#elif defined(HAVE_SIGACTION)
- sigemptyset(&newmask);
- sigaddset(&newmask, SIGTERM);
- sigaddset(&newmask, SIGCHLD);
- sigprocmask(SIG_BLOCK, &newmask, &holdmask);
-#endif /* HAVE_SIGSET */
-}
-
-
/*
* 'cupsdReleaseSignals()' - Release signals for delivery.
*/
@@ -2159,9 +2195,10 @@ usage(int status) /* O - Exit status */
"\n"
"-c config-file Load alternate configuration file\n"
"-f Run in the foreground\n"
- "-F Run in the foreground but detach\n"
+ "-F Run in the foreground but detach from console\n"
"-h Show this usage message\n"
- "-l Run cupsd from launchd(8)\n"));
+ "-l Run cupsd from launchd(8)\n"
+ "-t Test the configuration file\n"));
exit(status);
}
diff --git a/scheduler/mime.h b/scheduler/mime.h
index a6eb515dd..630b2d763 100644
--- a/scheduler/mime.h
+++ b/scheduler/mime.h
@@ -1,9 +1,9 @@
/*
* "$Id: mime.h 7694 2008-06-26 00:23:20Z mike $"
*
- * MIME type/conversion database definitions for the Common UNIX Printing System (CUPS).
+ * MIME type/conversion database definitions for CUPS.
*
- * Copyright 2007-2008 by Apple Inc.
+ * Copyright 2007-2010 by Apple Inc.
* Copyright 1997-2007 by Easy Software Products, all rights reserved.
*
* These coded instructions, statements, and computer programs are the
diff --git a/scheduler/network.h b/scheduler/network.h
index bbb081ade..95b6badc1 100644
--- a/scheduler/network.h
+++ b/scheduler/network.h
@@ -1,10 +1,9 @@
/*
* "$Id: network.h 6649 2007-07-11 21:46:42Z mike $"
*
- * Network interface definitions for the Common UNIX Printing System
- * (CUPS) scheduler.
+ * Network interface definitions for the CUPS scheduler.
*
- * Copyright 2007-2009 by Apple Inc.
+ * Copyright 2007-2010 by Apple Inc.
* Copyright 1997-2006 by Easy Software Products, all rights reserved.
*
* These coded instructions, statements, and computer programs are the
diff --git a/scheduler/policy.c b/scheduler/policy.c
index b7deab72a..bdca28728 100644
--- a/scheduler/policy.c
+++ b/scheduler/policy.c
@@ -1,9 +1,9 @@
/*
* "$Id: policy.c 7673 2008-06-18 22:31:26Z mike $"
*
- * Policy routines for the Common UNIX Printing System (CUPS).
+ * Policy routines for the CUPS scheduler.
*
- * Copyright 2007-2008 by Apple Inc.
+ * Copyright 2007-2010 by Apple Inc.
* Copyright 1997-2006 by Easy Software Products, all rights reserved.
*
* These coded instructions, statements, and computer programs are the
@@ -14,13 +14,19 @@
*
* Contents:
*
- * cupsdAddPolicy() - Add a policy to the system.
+ * AddPolicy() - Add a policy to the system.
* cupsdAddPolicyOp() - Add an operation to a policy.
- * cupsdCheckPolicy() - Check the IPP operation and username against
- * a policy.
+ * cupsdCheckPolicy() - Check the IPP operation and username against a
+ * policy.
* cupsdDeleteAllPolicies() - Delete all policies in memory.
* cupsdFindPolicy() - Find a named policy.
* cupsdFindPolicyOp() - Find a policy operation.
+ * cupsdGetPrivateAttrs() - Get the private attributes for the current
+ * request.
+ * compare_ops() - Compare two operations.
+ * compare_policies() - Compare two policies.
+ * free_policy() - Free the memory used by a policy.
+ * hash_op() - Generate a lookup hash for the operation.
*/
/*
@@ -28,6 +34,7 @@
*/
#include "cupsd.h"
+#include
/*
@@ -36,6 +43,7 @@
static int compare_ops(cupsd_location_t *a, cupsd_location_t *b);
static int compare_policies(cupsd_policy_t *a, cupsd_policy_t *b);
+static void free_policy(cupsd_policy_t *p);
static int hash_op(cupsd_location_t *op);
@@ -53,7 +61,10 @@ cupsdAddPolicy(const char *policy) /* I - Name of policy */
return (NULL);
if (!Policies)
- Policies = cupsArrayNew((cups_array_func_t)compare_policies, NULL);
+ Policies = cupsArrayNew3((cups_array_func_t)compare_policies, NULL,
+ (cups_ahash_func_t)NULL, 0,
+ (cups_acopy_func_t)NULL,
+ (cups_afree_func_t)free_policy);
if (!Policies)
return (NULL);
@@ -77,9 +88,7 @@ cupsdAddPolicyOp(cupsd_policy_t *p, /* I - Policy */
cupsd_location_t *po, /* I - Policy operation to copy */
ipp_op_t op) /* I - IPP operation code */
{
- int i; /* Looping var */
cupsd_location_t *temp; /* New policy operation */
- char name[1024]; /* Interface name */
cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdAddPolicyOp(p=%p, po=%p, op=%x(%s))",
@@ -89,72 +98,20 @@ cupsdAddPolicyOp(cupsd_policy_t *p, /* I - Policy */
return (NULL);
if (!p->ops)
- p->ops = cupsArrayNew2((cups_array_func_t)compare_ops, NULL,
- (cups_ahash_func_t)hash_op, 128);
+ p->ops = cupsArrayNew3((cups_array_func_t)compare_ops, NULL,
+ (cups_ahash_func_t)hash_op, 128,
+ (cups_acopy_func_t)NULL,
+ (cups_afree_func_t)cupsdFreeLocation);
if (!p->ops)
return (NULL);
- if ((temp = calloc(1, sizeof(cupsd_location_t))) != NULL)
+ if ((temp = cupsdCopyLocation(po)) != NULL)
{
temp->op = op;
temp->limit = CUPSD_AUTH_LIMIT_IPP;
cupsArrayAdd(p->ops, temp);
-
- if (po)
- {
- /*
- * Copy the specified policy to the new one...
- */
-
- temp->order_type = po->order_type;
- temp->type = po->type;
- temp->level = po->level;
- temp->satisfy = po->satisfy;
- temp->encryption = po->encryption;
-
- for (i = 0; i < po->num_names; i ++)
- cupsdAddName(temp, po->names[i]);
-
- for (i = 0; i < po->num_allow; i ++)
- switch (po->allow[i].type)
- {
- case CUPSD_AUTH_IP :
- cupsdAllowIP(temp, po->allow[i].mask.ip.address,
- po->allow[i].mask.ip.netmask);
- break;
-
- case CUPSD_AUTH_INTERFACE :
- snprintf(name, sizeof(name), "@IF(%s)",
- po->allow[i].mask.name.name);
- cupsdAllowHost(temp, name);
- break;
-
- default :
- cupsdAllowHost(temp, po->allow[i].mask.name.name);
- break;
- }
-
- for (i = 0; i < po->num_deny; i ++)
- switch (po->deny[i].type)
- {
- case CUPSD_AUTH_IP :
- cupsdDenyIP(temp, po->deny[i].mask.ip.address,
- po->deny[i].mask.ip.netmask);
- break;
-
- case CUPSD_AUTH_INTERFACE :
- snprintf(name, sizeof(name), "@IF(%s)",
- po->deny[i].mask.name.name);
- cupsdDenyHost(temp, name);
- break;
-
- default :
- cupsdDenyHost(temp, po->deny[i].mask.name.name);
- break;
- }
- }
}
return (temp);
@@ -211,8 +168,6 @@ cupsdCheckPolicy(cupsd_policy_t *p, /* I - Policy */
void
cupsdDeleteAllPolicies(void)
{
- cupsd_policy_t *p; /* Current policy */
- cupsd_location_t *po; /* Current policy op */
cupsd_printer_t *printer; /* Current printer */
@@ -228,24 +183,12 @@ cupsdDeleteAllPolicies(void)
printer = (cupsd_printer_t *)cupsArrayNext(Printers))
printer->op_policy_ptr = NULL;
+ DefaultPolicyPtr = NULL;
+
/*
* Then free all of the policies...
*/
- for (p = (cupsd_policy_t *)cupsArrayFirst(Policies);
- p;
- p = (cupsd_policy_t *)cupsArrayNext(Policies))
- {
- for (po = (cupsd_location_t *)cupsArrayFirst(p->ops);
- po;
- po = (cupsd_location_t *)cupsArrayNext(p->ops))
- cupsdDeleteLocation(po);
-
- cupsArrayDelete(p->ops);
- cupsdClearString(&p->name);
- free(p);
- }
-
cupsArrayDelete(Policies);
Policies = NULL;
@@ -326,6 +269,197 @@ cupsdFindPolicyOp(cupsd_policy_t *p, /* I - Policy */
}
+/*
+ * 'cupsdGetPrivateAttrs()' - Get the private attributes for the current
+ * request.
+ */
+
+cups_array_t * /* O - Array or NULL for no restrictions */
+cupsdGetPrivateAttrs(
+ cupsd_policy_t *policy, /* I - Policy */
+ cupsd_client_t *con, /* I - Client connection */
+ cupsd_printer_t *printer, /* I - Printer, if any */
+ const char *owner) /* I - Owner of object */
+{
+ char *name; /* Current name in access list */
+ cups_array_t *access_ptr, /* Access array */
+ *attrs_ptr; /* Attributes array */
+ const char *username; /* Username associated with request */
+ ipp_attribute_t *attr; /* Attribute from request */
+ struct passwd *pw; /* User info */
+
+
+#ifdef DEBUG
+ cupsdLogMessage(CUPSD_LOG_DEBUG2,
+ "cupsdGetPrivateAttrs(policy=%p(%s), con=%p(%d), "
+ "printer=%p(%s), owner=\"%s\")", policy, policy->name, con,
+ con->http.fd, printer, printer ? printer->name : "", owner);
+#endif /* DEBUG */
+
+ /*
+ * Get the access and attributes lists that correspond to the request...
+ */
+
+#ifdef DEBUG
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdGetPrivateAttrs: %s",
+ ippOpString(con->request->request.op.operation_id));
+#endif /* DEBUG */
+
+ switch (con->request->request.op.operation_id)
+ {
+ case IPP_GET_SUBSCRIPTIONS :
+ case IPP_GET_SUBSCRIPTION_ATTRIBUTES :
+ case IPP_GET_NOTIFICATIONS :
+ access_ptr = policy->sub_access;
+ attrs_ptr = policy->sub_attrs;
+ break;
+
+ default :
+ access_ptr = policy->job_access;
+ attrs_ptr = policy->job_attrs;
+ break;
+ }
+
+ /*
+ * If none of the attributes are private, return NULL now...
+ */
+
+ if ((name = (char *)cupsArrayFirst(attrs_ptr)) != NULL &&
+ !strcasecmp(name, "none"))
+ {
+#ifdef DEBUG
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdGetPrivateAttrs: Returning NULL.");
+#endif /* DEBUG */
+
+ return (NULL);
+ }
+
+ /*
+ * Otherwise check the user against the access list...
+ */
+
+ if (con->username[0])
+ username = con->username;
+ else if ((attr = ippFindAttribute(con->request, "requesting-user-name",
+ IPP_TAG_NAME)) != NULL)
+ username = attr->values[0].string.text;
+ else
+ username = "anonymous";
+
+ if (username[0])
+ {
+ pw = getpwnam(username);
+ endpwent();
+ }
+ else
+ pw = NULL;
+
+#ifdef DEBUG
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdGetPrivateAttrs: username=\"%s\"",
+ username);
+#endif /* DEBUG */
+
+ /*
+ * Otherwise check the user against the access list...
+ */
+
+ for (name = (char *)cupsArrayFirst(access_ptr);
+ name;
+ name = (char *)cupsArrayNext(access_ptr))
+ {
+#ifdef DEBUG
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdGetPrivateAttrs: name=%s", name);
+#endif /* DEBUG */
+
+ if (printer && !strcasecmp(name, "@ACL"))
+ {
+ char *acl; /* Current ACL user/group */
+
+ for (acl = (char *)cupsArrayFirst(printer->users);
+ acl;
+ acl = (char *)cupsArrayNext(printer->users))
+ {
+ if (acl[0] == '@')
+ {
+ /*
+ * Check group membership...
+ */
+
+ if (cupsdCheckGroup(username, pw, acl + 1))
+ break;
+ }
+ else if (acl[0] == '#')
+ {
+ /*
+ * Check UUID...
+ */
+
+ if (cupsdCheckGroup(username, pw, acl))
+ break;
+ }
+ else if (!strcasecmp(username, acl))
+ break;
+ }
+ }
+ else if (owner && !strcasecmp(name, "@OWNER") &&
+ !strcasecmp(username, owner))
+ {
+#ifdef DEBUG
+ cupsdLogMessage(CUPSD_LOG_DEBUG2,
+ "cupsdGetPrivateAttrs: Returning NULL.");
+#endif /* DEBUG */
+
+ return (NULL);
+ }
+ else if (!strcasecmp(name, "@SYSTEM"))
+ {
+ int i; /* Looping var */
+
+ for (i = 0; i < NumSystemGroups; i ++)
+ if (cupsdCheckGroup(username, pw, SystemGroups[i]))
+ {
+#ifdef DEBUG
+ cupsdLogMessage(CUPSD_LOG_DEBUG2,
+ "cupsdGetPrivateAttrs: Returning NULL.");
+#endif /* DEBUG */
+
+ return (NULL);
+ }
+ }
+ else if (name[0] == '@')
+ {
+ if (cupsdCheckGroup(username, pw, name + 1))
+ {
+#ifdef DEBUG
+ cupsdLogMessage(CUPSD_LOG_DEBUG2,
+ "cupsdGetPrivateAttrs: Returning NULL.");
+#endif /* DEBUG */
+
+ return (NULL);
+ }
+ }
+ else if (!strcasecmp(username, name))
+ {
+#ifdef DEBUG
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdGetPrivateAttrs: Returning NULL.");
+#endif /* DEBUG */
+
+ return (NULL);
+ }
+ }
+
+ /*
+ * No direct access, so return private attributes list...
+ */
+
+#ifdef DEBUG
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdGetPrivateAttrs: Returning list.");
+#endif /* DEBUG */
+
+ return (attrs_ptr);
+}
+
+
/*
* 'compare_ops()' - Compare two operations.
*/
@@ -350,6 +484,23 @@ compare_policies(cupsd_policy_t *a, /* I - First policy */
}
+/*
+ * 'free_policy()' - Free the memory used by a policy.
+ */
+
+static void
+free_policy(cupsd_policy_t *p) /* I - Policy to free */
+{
+ cupsArrayDelete(p->job_access);
+ cupsArrayDelete(p->job_attrs);
+ cupsArrayDelete(p->sub_access);
+ cupsArrayDelete(p->sub_attrs);
+ cupsArrayDelete(p->ops);
+ cupsdClearString(&p->name);
+ free(p);
+}
+
+
/*
* 'hash_op()' - Generate a lookup hash for the operation.
*/
diff --git a/scheduler/policy.h b/scheduler/policy.h
index d3c0c34b2..897b011f5 100644
--- a/scheduler/policy.h
+++ b/scheduler/policy.h
@@ -1,10 +1,9 @@
/*
* "$Id: policy.h 6895 2007-08-30 00:09:27Z mike $"
*
- * Policy definitions for the Common UNIX Printing System (CUPS)
- * scheduler.
+ * Policy definitions for the CUPS scheduler.
*
- * Copyright 2007 by Apple Inc.
+ * Copyright 2007-2010 by Apple Inc.
* Copyright 1997-2005 by Easy Software Products, all rights reserved.
*
* These coded instructions, statements, and computer programs are the
@@ -22,9 +21,15 @@
typedef struct
{
char *name; /* Policy name */
- cups_array_t *ops; /* Operations */
+ cups_array_t *job_access, /* Private users/groups for jobs */
+ *job_attrs, /* Private attributes for jobs */
+ *sub_access, /* Private users/groups for subscriptions */
+ *sub_attrs, /* Private attributes for subscriptions */
+ *ops; /* Operations */
} cupsd_policy_t;
+typedef struct cupsd_printer_s cupsd_printer_t;
+
/*
* Globals...
@@ -47,6 +52,10 @@ extern http_status_t cupsdCheckPolicy(cupsd_policy_t *p, cupsd_client_t *con,
extern void cupsdDeleteAllPolicies(void);
extern cupsd_policy_t *cupsdFindPolicy(const char *policy);
extern cupsd_location_t *cupsdFindPolicyOp(cupsd_policy_t *p, ipp_op_t op);
+extern cups_array_t *cupsdGetPrivateAttrs(cupsd_policy_t *p,
+ cupsd_client_t *con,
+ cupsd_printer_t *printer,
+ const char *owner);
/*
diff --git a/scheduler/printers.c b/scheduler/printers.c
index 537d6e4f4..8d2de325a 100644
--- a/scheduler/printers.c
+++ b/scheduler/printers.c
@@ -16,13 +16,11 @@
*
* cupsdAddPrinter() - Add a printer to the system.
* cupsdAddPrinterHistory() - Add the current printer state to the history.
- * cupsdAddPrinterUser() - Add a user to the ACL.
* cupsdCreateCommonData() - Create the common printer data.
* cupsdDeleteAllPrinters() - Delete all printers from the system.
* cupsdDeletePrinter() - Delete a printer from the system.
* cupsdFindDest() - Find a destination in the list.
* cupsdFindPrinter() - Find a printer in the list.
- * cupsdFreePrinterUsers() - Free allow/deny users.
* cupsdLoadAllPrinters() - Load printers from the printers.conf file.
* cupsdRenamePrinter() - Rename a printer.
* cupsdSaveAllPrinters() - Save all printer definitions to the
@@ -241,37 +239,6 @@ cupsdAddPrinterHistory(
}
-/*
- * 'cupsdAddPrinterUser()' - Add a user to the ACL.
- */
-
-void
-cupsdAddPrinterUser(
- cupsd_printer_t *p, /* I - Printer */
- const char *username) /* I - User */
-{
- const char **temp; /* Temporary array pointer */
-
-
- if (!p || !username)
- return;
-
- if (p->num_users == 0)
- temp = malloc(sizeof(char **));
- else
- temp = realloc(p->users, sizeof(char **) * (p->num_users + 1));
-
- if (!temp)
- return;
-
- p->users = temp;
- temp += p->num_users;
-
- if ((*temp = strdup(username)) != NULL)
- p->num_users ++;
-}
-
-
/*
* 'cupsdCreateCommonData()' - Create the common printer data.
*/
@@ -931,7 +898,7 @@ cupsdDeletePrinter(
delete_string_array(&(p->filters));
delete_string_array(&(p->pre_filters));
- cupsdFreePrinterUsers(p);
+ cupsdFreeStrings(&(p->users));
cupsdFreeQuotas(p);
cupsdClearString(&p->uri);
@@ -1007,30 +974,6 @@ cupsdFindPrinter(const char *name) /* I - Name of printer to find */
}
-/*
- * 'cupsdFreePrinterUsers()' - Free allow/deny users.
- */
-
-void
-cupsdFreePrinterUsers(
- cupsd_printer_t *p) /* I - Printer */
-{
- int i; /* Looping var */
-
-
- if (!p || !p->num_users)
- return;
-
- for (i = 0; i < p->num_users; i ++)
- free((void *)p->users[i]);
-
- free(p->users);
-
- p->num_users = 0;
- p->users = NULL;
-}
-
-
/*
* 'cupsdLoadAllPrinters()' - Load printers from the printers.conf file.
*/
@@ -1399,7 +1342,7 @@ cupsdLoadAllPrinters(void)
if (value)
{
p->deny_users = 0;
- cupsdAddPrinterUser(p, value);
+ cupsdAddString(&(p->users), value);
}
else
cupsdLogMessage(CUPSD_LOG_ERROR,
@@ -1410,7 +1353,7 @@ cupsdLoadAllPrinters(void)
if (value)
{
p->deny_users = 1;
- cupsdAddPrinterUser(p, value);
+ cupsdAddString(&(p->users), value);
}
else
cupsdLogMessage(CUPSD_LOG_ERROR,
@@ -1583,7 +1526,8 @@ cupsdSaveAllPrinters(void)
char temp[1024], /* Temporary string */
backup[1024], /* printers.conf.O file */
value[2048], /* Value string */
- *ptr; /* Pointer into value */
+ *ptr, /* Pointer into value */
+ *name; /* Current user/group name */
cupsd_printer_t *printer; /* Current printer class */
time_t curtime; /* Current time */
struct tm *curdate; /* Current date */
@@ -1756,9 +1700,10 @@ cupsdSaveAllPrinters(void)
cupsFilePrintf(fp, "PageLimit %d\n", printer->page_limit);
cupsFilePrintf(fp, "KLimit %d\n", printer->k_limit);
- for (i = 0; i < printer->num_users; i ++)
- cupsFilePutConf(fp, printer->deny_users ? "DenyUser" : "AllowUser",
- printer->users[i]);
+ for (name = (char *)cupsArrayFirst(printer->users);
+ name;
+ name = (char *)cupsArrayNext(printer->users))
+ cupsFilePutConf(fp, printer->deny_users ? "DenyUser" : "AllowUser", name);
if (printer->op_policy)
cupsFilePutConf(fp, "OpPolicy", printer->op_policy);
@@ -2263,7 +2208,8 @@ cupsdSetPrinterAttrs(cupsd_printer_t *p)/* I - Printer to setup */
ipp_t *oldattrs; /* Old printer attributes */
ipp_attribute_t *attr; /* Attribute data */
cups_option_t *option; /* Current printer option */
- char *filter; /* Current filter */
+ char *name, /* Current user/group name */
+ *filter; /* Current filter */
static const char * const air_none[] =
{ /* No authentication */
"none"
@@ -2366,16 +2312,21 @@ cupsdSetPrinterAttrs(cupsd_printer_t *p)/* I - Printer to setup */
ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-info",
NULL, p->info ? p->info : "");
- if (p->num_users)
+ if (cupsArrayCount(p->users) > 0)
{
if (p->deny_users)
- ippAddStrings(p->attrs, IPP_TAG_PRINTER, IPP_TAG_NAME,
- "requesting-user-name-denied", p->num_users, NULL,
- p->users);
+ attr = ippAddStrings(p->attrs, IPP_TAG_PRINTER, IPP_TAG_NAME,
+ "requesting-user-name-denied",
+ cupsArrayCount(p->users), NULL, NULL);
else
- ippAddStrings(p->attrs, IPP_TAG_PRINTER, IPP_TAG_NAME,
- "requesting-user-name-allowed", p->num_users, NULL,
- p->users);
+ attr = ippAddStrings(p->attrs, IPP_TAG_PRINTER, IPP_TAG_NAME,
+ "requesting-user-name-allowed",
+ cupsArrayCount(p->users), NULL, NULL);
+
+ for (i = 0, name = (char *)cupsArrayFirst(p->users);
+ name;
+ i ++, name = (char *)cupsArrayNext(p->users))
+ attr->values[i].string.text = _cupsStrRetain(name);
}
ippAddInteger(p->attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
diff --git a/scheduler/printers.h b/scheduler/printers.h
index f594a2492..5a62a5da9 100644
--- a/scheduler/printers.h
+++ b/scheduler/printers.h
@@ -1,9 +1,9 @@
/*
* "$Id: printers.h 7564 2008-05-15 00:57:43Z mike $"
*
- * Printer definitions for the Common UNIX Printing System (CUPS) scheduler.
+ * Printer definitions for the CUPS scheduler.
*
- * Copyright 2007-2008 by Apple Inc.
+ * Copyright 2007-2010 by Apple Inc.
* Copyright 1997-2007 by Easy Software Products, all rights reserved.
*
* These coded instructions, statements, and computer programs are the
@@ -38,7 +38,7 @@ typedef struct
typedef struct cupsd_job_s cupsd_job_t;
-typedef struct cupsd_printer_s
+struct cupsd_printer_s
{
char *uri, /* Printer URI */
*hostname, /* Host printer resides on */
@@ -81,9 +81,8 @@ typedef struct cupsd_printer_s
page_limit, /* Maximum number of pages */
k_limit; /* Maximum number of kilobytes */
cups_array_t *quotas; /* Quota records */
- int deny_users, /* 1 = deny, 0 = allow */
- num_users; /* Number of allowed/denied users */
- const char **users; /* Allowed/denied users */
+ int deny_users; /* 1 = deny, 0 = allow */
+ cups_array_t *users; /* Allowed/denied users */
int num_history; /* Number of history collections */
ipp_t **history; /* History data */
int sequence_number; /* Increasing sequence number */
@@ -109,7 +108,7 @@ typedef struct cupsd_printer_s
DNSServiceRef ipp_ref, /* Reference for _ipp._tcp,_cups */
printer_ref; /* Reference for _printer._tcp */
#endif /* HAVE_DNSSD */
-} cupsd_printer_t;
+};
/*
@@ -139,8 +138,6 @@ VAR cupsd_policy_t *DefaultPolicyPtr
extern cupsd_printer_t *cupsdAddPrinter(const char *name);
extern void cupsdAddPrinterHistory(cupsd_printer_t *p);
-extern void cupsdAddPrinterUser(cupsd_printer_t *p,
- const char *username);
extern void cupsdCreateCommonData(void);
extern void cupsdDeleteAllPrinters(void);
extern int cupsdDeletePrinter(cupsd_printer_t *p, int update);
@@ -148,7 +145,6 @@ extern cupsd_printer_t *cupsdFindDest(const char *name);
extern cupsd_printer_t *cupsdFindPrinter(const char *name);
extern cupsd_quota_t *cupsdFindQuota(cupsd_printer_t *p,
const char *username);
-extern void cupsdFreePrinterUsers(cupsd_printer_t *p);
extern void cupsdFreeQuotas(cupsd_printer_t *p);
extern void cupsdLoadAllPrinters(void);
extern void cupsdRenamePrinter(cupsd_printer_t *p,
diff --git a/scheduler/quotas.c b/scheduler/quotas.c
index eb6277102..15f1b37b3 100644
--- a/scheduler/quotas.c
+++ b/scheduler/quotas.c
@@ -1,7 +1,7 @@
/*
* "$Id: quotas.c 6947 2007-09-12 21:09:49Z mike $"
*
- * Quota routines for the Common UNIX Printing System (CUPS).
+ * Quota routines for the CUPS scheduler.
*
* Copyright 2007-2010 by Apple Inc.
* Copyright 1997-2007 by Easy Software Products.
diff --git a/scheduler/removefile.c b/scheduler/removefile.c
index 213d795ea..756912e99 100644
--- a/scheduler/removefile.c
+++ b/scheduler/removefile.c
@@ -1,9 +1,9 @@
/*
* "$Id: removefile.c 7720 2008-07-11 22:46:21Z mike $"
*
- * "Secure" file removal function for the Common UNIX Printing System (CUPS).
+ * "Secure" file removal function for the CUPS scheduler.
*
- * Copyright 2007 by Apple Inc.
+ * Copyright 2007-2010 by Apple Inc.
* Copyright 1997-2007 by Easy Software Products, all rights reserved.
*
* These coded instructions, statements, and computer programs are the
@@ -107,8 +107,10 @@ cupsdRemoveFile(const char *filename) /* I - File to remove */
return (-1);
}
+ CUPS_SRAND(time(NULL));
+
for (i = 0; i < sizeof(buffer); i ++)
- buffer[i] = rand();
+ buffer[i] = CUPS_RAND();
if (overwrite_data(fd, buffer, sizeof(buffer), (int)info.st_size))
{
close(fd);
@@ -130,7 +132,7 @@ cupsdRemoveFile(const char *filename) /* I - File to remove */
}
for (i = 0; i < sizeof(buffer); i ++)
- buffer[i] = rand();
+ buffer[i] = CUPS_RAND();
if (overwrite_data(fd, buffer, sizeof(buffer), (int)info.st_size))
{
close(fd);
diff --git a/scheduler/select.c b/scheduler/select.c
index 03e47437a..2965c6cb0 100644
--- a/scheduler/select.c
+++ b/scheduler/select.c
@@ -1,7 +1,7 @@
/*
* "$Id: select.c 7720 2008-07-11 22:46:21Z mike $"
*
- * Select abstraction functions for the Common UNIX Printing System (CUPS).
+ * Select abstraction functions for the CUPS scheduler.
*
* Copyright 2007-2010 by Apple Inc.
* Copyright 2006-2007 by Easy Software Products.
diff --git a/scheduler/statbuf.c b/scheduler/statbuf.c
index 6da11175a..e719aebdb 100644
--- a/scheduler/statbuf.c
+++ b/scheduler/statbuf.c
@@ -1,10 +1,9 @@
/*
* "$Id: statbuf.c 7674 2008-06-18 23:18:32Z mike $"
*
- * Status buffer routines for the Common UNIX Printing System (CUPS)
- * scheduler.
+ * Status buffer routines for the CUPS scheduler.
*
- * Copyright 2007-2009 by Apple Inc.
+ * Copyright 2007-2010 by Apple Inc.
* Copyright 1997-2006 by Easy Software Products, all rights reserved.
*
* These coded instructions, statements, and computer programs are the
diff --git a/scheduler/statbuf.h b/scheduler/statbuf.h
index c42c6fdb7..1ca227213 100644
--- a/scheduler/statbuf.h
+++ b/scheduler/statbuf.h
@@ -1,10 +1,9 @@
/*
* "$Id: statbuf.h 7674 2008-06-18 23:18:32Z mike $"
*
- * Status buffer definitions for the Common UNIX Printing System (CUPS)
- * scheduler.
+ * Status buffer definitions for the CUPS scheduler.
*
- * Copyright 2007-2008 by Apple Inc.
+ * Copyright 2007-2010 by Apple Inc.
* Copyright 1997-2005 by Easy Software Products, all rights reserved.
*
* These coded instructions, statements, and computer programs are the
@@ -19,7 +18,7 @@
* Constants...
*/
-#define CUPSD_SB_BUFFER_SIZE 1024 /* Bytes or job status buffer */
+#define CUPSD_SB_BUFFER_SIZE 2048 /* Bytes for job status buffer */
/*
diff --git a/scheduler/subscriptions.c b/scheduler/subscriptions.c
index 4781ac147..92dffe642 100644
--- a/scheduler/subscriptions.c
+++ b/scheduler/subscriptions.c
@@ -1,9 +1,9 @@
/*
* "$Id: subscriptions.c 7824 2008-08-01 21:11:55Z mike $"
*
- * Subscription routines for the Common UNIX Printing System (CUPS) scheduler.
+ * Subscription routines for the CUPS scheduler.
*
- * Copyright 2007-2009 by Apple Inc.
+ * Copyright 2007-2010 by Apple Inc.
* Copyright 1997-2007 by Easy Software Products, all rights reserved.
*
* These coded instructions, statements, and computer programs are the
@@ -480,9 +480,6 @@ cupsdDeleteSubscription(
cupsd_subscription_t *sub, /* I - Subscription object */
int update) /* I - 1 = update subscriptions.conf */
{
- int i; /* Looping var */
-
-
/*
* Close the pipe to the notifier as needed...
*/
@@ -503,13 +500,7 @@ cupsdDeleteSubscription(
cupsdClearString(&(sub->owner));
cupsdClearString(&(sub->recipient));
- if (sub->events)
- {
- for (i = 0; i < sub->num_events; i ++)
- cupsd_delete_event(sub->events[i]);
-
- free(sub->events);
- }
+ cupsArrayDelete(sub->events);
free(sub);
@@ -1426,7 +1417,10 @@ cupsd_send_notification(
if (!sub->events)
{
- sub->events = calloc(MaxEvents, sizeof(cupsd_event_t *));
+ sub->events = cupsArrayNew3((cups_array_func_t)NULL, NULL,
+ (cups_ahash_func_t)NULL, 0,
+ (cups_acopy_func_t)NULL,
+ (cups_afree_func_t)cupsd_delete_event);
if (!sub->events)
{
@@ -1441,19 +1435,15 @@ cupsd_send_notification(
* Purge an old event as needed...
*/
- if (sub->num_events >= MaxEvents)
+ if (cupsArrayCount(sub->events) >= MaxEvents)
{
/*
* Purge the oldest event in the cache...
*/
- cupsd_delete_event(sub->events[0]);
+ cupsArrayRemove(sub->events, cupsArrayFirst(sub->events));
- sub->num_events --;
sub->first_event_id ++;
-
- memmove(sub->events, sub->events + 1,
- sub->num_events * sizeof(cupsd_event_t *));
}
/*
@@ -1463,8 +1453,7 @@ cupsd_send_notification(
* event cache limit, we don't need to check for overflow here...
*/
- sub->events[sub->num_events] = event;
- sub->num_events ++;
+ cupsArrayAdd(sub->events, event);
/*
* Deliver the event...
diff --git a/scheduler/subscriptions.h b/scheduler/subscriptions.h
index b807ac215..2a2714ec1 100644
--- a/scheduler/subscriptions.h
+++ b/scheduler/subscriptions.h
@@ -1,9 +1,9 @@
/*
* "$Id: subscriptions.h 7824 2008-08-01 21:11:55Z mike $"
*
- * Subscription definitions for the Common UNIX Printing System (CUPS) scheduler.
+ * Subscription definitions for the CUPS scheduler.
*
- * Copyright 2007-2008 by Apple Inc.
+ * Copyright 2007-2010 by Apple Inc.
* Copyright 1997-2007 by Easy Software Products, all rights reserved.
*
* These coded instructions, statements, and computer programs are the
@@ -100,9 +100,8 @@ typedef struct cupsd_subscription_s /**** Subscription structure ****/
time_t last; /* Time of last notification */
time_t expire; /* Lease expiration time */
int first_event_id, /* First event-id in cache */
- next_event_id, /* Next event-id to use */
- num_events; /* Number of cached events */
- cupsd_event_t **events; /* Cached events */
+ next_event_id; /* Next event-id to use */
+ cups_array_t *events; /* Cached events */
} cupsd_subscription_t;
diff --git a/scheduler/sysman.c b/scheduler/sysman.c
index 1c548b6ca..e5c138e28 100644
--- a/scheduler/sysman.c
+++ b/scheduler/sysman.c
@@ -1,9 +1,9 @@
/*
* "$Id: sysman.c 7928 2008-09-10 22:14:22Z mike $"
*
- * System management definitions for the Common UNIX Printing System (CUPS).
+ * System management functions for the CUPS scheduler.
*
- * Copyright 2007-2009 by Apple Inc.
+ * Copyright 2007-2010 by Apple Inc.
* Copyright 2006 by Easy Software Products.
*
* These coded instructions, statements, and computer programs are the
@@ -52,7 +52,7 @@
*
* Power management support is currently only implemented on MacOS X, but
* essentially we use four functions to let the OS know when it is OK to
- * put the system to idle sleep, typically when we are not in the middle of
+ * put the system to sleep, typically when we are not in the middle of
* printing a job.
*
* Once put to sleep, we invalidate all remote printers since it is common
diff --git a/scheduler/sysman.h b/scheduler/sysman.h
index 231fc2c54..0983f109d 100644
--- a/scheduler/sysman.h
+++ b/scheduler/sysman.h
@@ -1,9 +1,9 @@
/*
* "$Id: sysman.h 7928 2008-09-10 22:14:22Z mike $"
*
- * System management definitions for the Common UNIX Printing System (CUPS).
+ * System management definitions for the CUPS scheduler.
*
- * Copyright 2007-2008 by Apple Inc.
+ * Copyright 2007-2010 by Apple Inc.
* Copyright 2006 by Easy Software Products.
*
* These coded instructions, statements, and computer programs are the
diff --git a/scheduler/util.c b/scheduler/util.c
index db920c225..b170f8052 100644
--- a/scheduler/util.c
+++ b/scheduler/util.c
@@ -1,9 +1,9 @@
/*
* "$Id: util.c 7621 2008-06-06 18:55:35Z mike $"
*
- * Mini-daemon utility functions for the Common UNIX Printing System (CUPS).
+ * Mini-daemon utility functions for CUPS.
*
- * Copyright 2007-2009 by Apple Inc.
+ * Copyright 2007-2010 by Apple Inc.
* Copyright 1997-2005 by Easy Software Products.
*
* These coded instructions, statements, and computer programs are the
@@ -163,13 +163,16 @@ cupsdCreateStringsArray(const char *s) /* I - Comma-delimited strings */
cups_array_t *a; /* CUPS array */
const char *start, /* Start of string */
*end; /* End of string */
- char *ptr; /* New string */
+ char buffer[8192]; /* New string */
if (!s)
return (NULL);
- if ((a = cupsArrayNew((cups_array_func_t)strcmp, NULL)) != NULL)
+ if ((a = cupsArrayNew3((cups_array_func_t)strcmp, NULL,
+ (cups_ahash_func_t)NULL, 0,
+ (cups_acopy_func_t)_cupsStrAlloc,
+ (cups_afree_func_t)_cupsStrFree)) != NULL)
{
for (start = end = s; *end; start = end + 1)
{
@@ -178,17 +181,26 @@ cupsdCreateStringsArray(const char *s) /* I - Comma-delimited strings */
*/
if ((end = strchr(start, ',')) == NULL)
- end = start + strlen(start);
+ {
+ /*
+ * Last delimited string...
+ */
+
+ cupsArrayAdd(a, (char *)start);
+ break;
+ }
/*
- * Duplicate the string and add it to the array...
+ * Copy the string and add it to the array...
*/
- if ((ptr = calloc(1, end - start + 1)) == NULL)
+ if ((end - start + 1) > sizeof(buffer))
break;
- memcpy(ptr, start, end - start);
- cupsArrayAdd(a, ptr);
+ memcpy(buffer, start, end - start);
+ buffer[end - start] = '\0';
+
+ cupsArrayAdd(a, buffer);
}
}
diff --git a/scheduler/util.h b/scheduler/util.h
index fab50eee5..ecf7645a4 100644
--- a/scheduler/util.h
+++ b/scheduler/util.h
@@ -1,9 +1,9 @@
/*
* "$Id: util.h 7711 2008-07-02 04:39:27Z mike $"
*
- * Mini-daemon utility definitions for the Common UNIX Printing System (CUPS).
+ * Mini-daemon utility definitions for CUPS.
*
- * Copyright 2007-2009 by Apple Inc.
+ * Copyright 2007-2010 by Apple Inc.
* Copyright 1997-2005 by Easy Software Products.
*
* These coded instructions, statements, and computer programs are the
diff --git a/test/4.4-subscription-ops.test b/test/4.4-subscription-ops.test
index f63cfcbd2..f6cf820f1 100644
--- a/test/4.4-subscription-ops.test
+++ b/test/4.4-subscription-ops.test
@@ -16,6 +16,7 @@
ATTR charset attributes-charset utf-8
ATTR language attributes-natural-language en
ATTR uri printer-uri $scheme://$hostname:$port/printers/Test1
+ ATTR name requesting-user-name $user
GROUP subscription
ATTR uri notify-recipient-uri testnotify://
@@ -48,6 +49,7 @@
ATTR language attributes-natural-language en
ATTR uri printer-uri $scheme://$hostname:$port/printers/Test1
ATTR integer notify-subscription-id $notify-subscription-id
+ ATTR name requesting-user-name $user
# What statuses are OK?
STATUS client-error-not-found
@@ -69,6 +71,7 @@
ATTR charset attributes-charset utf-8
ATTR language attributes-natural-language en
ATTR uri printer-uri $scheme://$hostname:$port/printers/Test1
+ ATTR name requesting-user-name $user
GROUP subscription
ATTR uri notify-recipient-uri testnotify://
@@ -102,6 +105,7 @@
ATTR charset attributes-charset utf-8
ATTR language attributes-natural-language en
ATTR uri printer-uri $scheme://$hostname:$port/printers/Test1
+ ATTR name requesting-user-name $user
# What statuses are OK?
STATUS successful-ok
@@ -129,6 +133,7 @@
ATTR charset attributes-charset utf-8
ATTR language attributes-natural-language en
ATTR uri printer-uri $scheme://$hostname:$port/printers/Test1
+ ATTR name requesting-user-name $user
GROUP subscription
ATTR uri notify-recipient-uri testnotify://
diff --git a/test/get-printer-attributes.test b/test/get-printer-attributes.test
index 54ce778b2..5940017a0 100644
--- a/test/get-printer-attributes.test
+++ b/test/get-printer-attributes.test
@@ -1,16 +1,13 @@
# Get printer attributes using get-printer-attributes
{
# The name of the test...
- NAME "Get printer attributes using get-printer-attributes"
-
- # The resource to use for the POST
- # RESOURCE /admin
+ NAME "Get printer attributes using Get-Printer-Attributes"
# The operation to use
- OPERATION get-printer-attributes
+ OPERATION Get-Printer-Attributes
# Attributes, starting in the operation group...
- GROUP operation
+ GROUP operation-attributes-tag
ATTR charset attributes-charset utf-8
ATTR language attributes-natural-language en
ATTR uri printer-uri $uri
diff --git a/test/ipp-1.1.test b/test/ipp-1.1.test
index eb547fb01..dc3147090 100644
--- a/test/ipp-1.1.test
+++ b/test/ipp-1.1.test
@@ -226,7 +226,7 @@
EXPECT ipp-versions-supported OF-TYPE keyword IN-GROUP printer-attributes-tag WITH-VALUE 1.1
EXPECT natural-language-configured OF-TYPE naturalLanguage IN-GROUP printer-attributes-tag COUNT 1
EXPECT operations-supported OF-TYPE enum IN-GROUP printer-attributes-tag WITH-VALUE 0x0002 # Print-Job
- # Not requiring 0x0004 Validate-Job since it is deprecated
+ EXPECT operations-supported WITH-VALUE 0x0004 # Validate-Job
EXPECT operations-supported WITH-VALUE 0x0008 # Cancel-Job
EXPECT operations-supported WITH-VALUE 0x0009 # Get-Job-Attributes
EXPECT operations-supported WITH-VALUE 0x000a # Get-Jobs
diff --git a/test/ipptool.c b/test/ipptool.c
index 330c5212d..6832f9d34 100644
--- a/test/ipptool.c
+++ b/test/ipptool.c
@@ -36,6 +36,7 @@
* print_xml_string() - Print an XML string with escaping.
* print_xml_trailer() - Print the XML trailer with success/fail value.
* set_variable() - Set a variable value.
+ * timeout_cb() - Handle HTTP timeouts.
* usage() - Show program usage.
* validate_attr() - Determine whether an attribute is valid.
* with_value() - Test a WITH-VALUE predicate.
@@ -115,6 +116,7 @@ typedef struct _cups_vars_s /**** Set of variables ****/
resource[1024]; /* Resource path from URI */
int port; /* Port number from URI */
http_encryption_t encryption; /* Encryption for connection? */
+ double timeout; /* Timeout for connection */
cups_array_t *vars; /* Array of variables */
} _cups_vars_t;
@@ -191,6 +193,7 @@ static void print_xml_string(const char *element, const char *s);
static void print_xml_trailer(int success, const char *message);
static void set_variable(_cups_vars_t *vars, const char *name,
const char *value);
+static int timeout_cb(http_t *http, void *user_data);
static void usage(void);
static int validate_attr(ipp_attribute_t *attr, int print);
static int with_value(char *value, int regex, ipp_attribute_t *attr,
@@ -213,7 +216,7 @@ main(int argc, /* I - Number of command-line args */
filename[1024], /* Real filename */
testname[1024]; /* Real test filename */
const char *testfile; /* Test file to use */
- int interval, /* Test interval */
+ int interval, /* Test interval in microseconds */
repeat; /* Repeat count */
_cups_vars_t vars; /* Variables */
http_uri_status_t uri_status; /* URI separation status */
@@ -282,6 +285,19 @@ main(int argc, /* I - Number of command-line args */
#endif /* HAVE_SSL */
break;
+ case 'T' : /* Set timeout */
+ i ++;
+
+ if (i >= argc)
+ {
+ _cupsLangPuts(stderr,
+ _("ipptool: Missing timeout for \"-T\".\n"));
+ usage();
+ }
+
+ vars.timeout = _cupsStrScand(argv[i], NULL, localeconv());
+ break;
+
case 'V' : /* Set IPP version */
i ++;
@@ -378,7 +394,16 @@ main(int argc, /* I - Number of command-line args */
usage();
}
else
- interval = atoi(argv[i]);
+ {
+ interval = (int)(_cupsStrScand(argv[i], NULL, localeconv()) *
+ 1000000.0);
+ if (interval <= 0)
+ {
+ _cupsLangPuts(stderr,
+ _("ipptool: Invalid seconds for \"-i\".\n"));
+ usage();
+ }
+ }
if (Output == _CUPS_OUTPUT_PLIST && interval)
{
@@ -517,20 +542,20 @@ main(int argc, /* I - Number of command-line args */
if (Output == _CUPS_OUTPUT_PLIST)
print_xml_trailer(!status, NULL);
- else if (interval && repeat > 0)
+ else if (interval > 0 && repeat > 0)
{
while (repeat > 1)
{
- sleep(interval);
+ usleep(interval);
do_tests(&vars, testfile);
repeat --;
}
}
- else if (interval)
+ else if (interval > 0)
{
for (;;)
{
- sleep(interval);
+ usleep(interval);
do_tests(&vars, testfile);
}
}
@@ -628,6 +653,9 @@ do_tests(_cups_vars_t *vars, /* I - Variables */
goto test_exit;
}
+ if (vars->timeout > 0.0)
+ _httpSetTimeout(http, vars->timeout, timeout_cb, NULL);
+
/*
* Loop on tests...
*/
@@ -1194,7 +1222,7 @@ do_tests(_cups_vars_t *vars, /* I - Variables */
* Delay before operation...
*/
- int delay;
+ double delay;
if (!get_token(fp, token, sizeof(token), &linenum))
{
@@ -1203,7 +1231,7 @@ do_tests(_cups_vars_t *vars, /* I - Variables */
goto test_exit;
}
- if ((delay = atoi(token)) <= 0)
+ if ((delay = _cupsStrScand(token, NULL, localeconv())) <= 0.0)
{
print_fatal_error("Bad DELAY value \"%s\" on line %d.", token,
linenum);
@@ -1213,9 +1241,9 @@ do_tests(_cups_vars_t *vars, /* I - Variables */
else
{
if (Output == _CUPS_OUTPUT_TEST)
- printf(" [%d second delay]\n", delay);
+ printf(" [%g second delay]\n", delay);
- sleep(delay);
+ usleep((int)(1000000.0 * delay));
}
}
else if (!strcasecmp(token, "ATTR"))
@@ -3687,6 +3715,21 @@ set_variable(_cups_vars_t *vars, /* I - Variables */
}
+/*
+ * 'timeout_cb()' - Handle HTTP timeouts.
+ */
+
+static int /* O - 1 to continue, 0 to cancel */
+timeout_cb(http_t *http, /* I - Connection to server (unused) */
+ void *user_data) /* I - User data (unused) */
+{
+ (void)http;
+ (void)user_data;
+
+ return (0);
+}
+
+
/*
* 'usage()' - Show program usage.
*/
@@ -3705,6 +3748,7 @@ usage(void)
"-I Ignore errors\n"
"-L Send requests using content-length\n"
"-S Test with SSL encryption.\n"
+ "-T Set the receive/send timeout in seconds.\n"
"-V version Set default IPP version.\n"
"-X Produce XML plist instead of plain text.\n"
"-d name=value Define variable.\n"
@@ -4526,6 +4570,65 @@ with_value(char *value, /* I - Value string */
}
break;
+ case IPP_TAG_RANGE :
+ for (i = 0; i < attr->num_values; i ++)
+ {
+ char op, /* Comparison operator */
+ *nextptr; /* Next pointer */
+ int intvalue; /* Integer value */
+
+
+ valptr = value;
+ if (!strncmp(valptr, "no-value,", 9))
+ valptr += 9;
+
+ while (isspace(*valptr & 255) || isdigit(*valptr & 255) ||
+ *valptr == '-' || *valptr == ',' || *valptr == '<' ||
+ *valptr == '=' || *valptr == '>')
+ {
+ op = '=';
+ while (*valptr && !isdigit(*valptr & 255) && *valptr != '-')
+ {
+ if (*valptr == '<' || *valptr == '>' || *valptr == '=')
+ op = *valptr;
+ valptr ++;
+ }
+
+ if (!*valptr)
+ break;
+
+ intvalue = strtol(valptr, &nextptr, 0);
+ if (nextptr == valptr)
+ break;
+ valptr = nextptr;
+
+ switch (op)
+ {
+ case '=' :
+ if (attr->values[i].range.upper == intvalue)
+ return (1);
+ break;
+ case '<' :
+ if (attr->values[i].range.upper < intvalue)
+ return (1);
+ break;
+ case '>' :
+ if (attr->values[i].range.upper > intvalue)
+ return (1);
+ break;
+ }
+ }
+ }
+
+ if (report)
+ {
+ for (i = 0; i < attr->num_values; i ++)
+ print_test_error("GOT: %s=%d-%d", attr->name,
+ attr->values[i].range.lower,
+ attr->values[i].range.upper);
+ }
+ break;
+
case IPP_TAG_BOOLEAN :
for (i = 0; i < attr->num_values; i ++)
{
diff --git a/test/print-job-media-col.test b/test/print-job-media-col.test
index ed4f73b5d..cafd291fb 100644
--- a/test/print-job-media-col.test
+++ b/test/print-job-media-col.test
@@ -32,6 +32,7 @@
MEMBER integer media-top-margin 0
MEMBER integer media-bottom-margin 0
}
+ ATTR enum print-quality 5
FILE $filename
diff --git a/test/run-stp-tests.sh b/test/run-stp-tests.sh
index 1d0973b9d..a1a3536e5 100755
--- a/test/run-stp-tests.sh
+++ b/test/run-stp-tests.sh
@@ -736,10 +736,10 @@ fi
# Warning log messages
count=`grep '^W ' /tmp/cups-$user/log/error_log | wc -l | awk '{print $1}'`
-if test $count != 0; then
- echo "FAIL: $count warning messages, expected 0."
+if test $count != 9; then
+ echo "FAIL: $count warning messages, expected 9."
grep '^W ' /tmp/cups-$user/log/error_log
- echo "FAIL: $count warning messages, expected 0.
" >>$strfile
+ echo "FAIL: $count warning messages, expected 9.
" >>$strfile
echo "" >>$strfile
grep '^W ' /tmp/cups-$user/log/error_log | sed -e '1,$s/&/&/g' -e '1,$s/</g' >>$strfile
echo "
" >>$strfile
--
2.39.5